'Is it possible to assign a partial wildcard to a type in typescript?

I search for a while to see if it is possible, i could not find anything, but maybe what i want is possible and i just searched with the wrong search terms.

What i want to do

type a = 'String' | 'String/' + string;
const b: a = 'String/anything';


Solution 1:[1]

Works as of Typescript v4.1 with the introduction of template literals:

type a = "String" | `String/${string}`
const b: a = "String" // Valid
const c: a = "String123" // Invalid
const d: a = "String/123" // Valid
const e: a = "String/" // Valid

Typescript Playground Link

Solution 2:[2]

TS4.1+

Pattern template literals, as implemented in ms/TS#40598 and introduced with TS4.1, now allow this:

type a = 'String' | `String/${string}`;
const b: a = 'String/anything';

See the other answer also.


TS4.0-

TypeScript does not have this feature (as of v3.5, anyway). There is an existing suggestion to allow using regular expressions to pick out subtypes of string. If that were implemented, you would be able to do something like:

// THE FOLLOWING CODE IS NOT VALID TYPESCRIPT, DO NOT USE
type a = /^String(\/.*)?$/;
const b: a = "String/anything"; // okay

If you really want to see this happen you might want to go over to that issue in GitHub and give it a ? or describe your use case if you think it's more compelling than what's there already.


The closest workaround you could use today would be something without any compile-time validation. You could make a branded primitive to stand for your a type, and a user-defined type guard function to perform validation at runtime instead of compile time:

type a = string & { __brand: "type a" };
function isA(x: string): x is a {
  return /^String(\/.*)?$/.test(x);
}

Then you could define b like:

const b = "String/anything";
if (!isA(b)) throw new Error(b + "does not match type a");

and, after that code, b is known to be of type a by the compiler:

function acceptOnlyA(a: a) {}
acceptOnlyA(b); // okay

So that works as far as it goes.


Okay, hope that helps. Good luck!

Link to code

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ScarpMetal
Solution 2