How do you create a Typescript string type, which includes values from a union type AND is separated by commas?
I think this doesn't exist, but I'm asking anyway...
type AcceptableVal = 'cool' | 'wow' | 'biz' | 'sweet' | 'yowza' | 'fantastic';
type Amaze = // how do you define this?;
const dabes: Amaze = 'cool,wow';
const fancy: Amaze = 'biz,wow,fantastic';
const hachiMachi: Amaze = 'yowza,biz,sweet';
You can now use string template literal types to define a pattern like:
type S = 'cool' | 'wow' | 'biz' | 'sweet' | 'yowza' | 'fantastic';
type Test = `${S},${S}`
What you still can't do is make this infinitely extensible, like an array. To make this work typescript generates every single combination as a union. But for small lists like this it can work.
For example:
type S = 'cool' | 'wow' | 'biz' | 'sweet' | 'yowza' | 'fantastic';
type Amaze =
| `${S}`
| `${S},${S}`
| `${S},${S},${S}`
| `${S},${S},${S},${S}`
| `${S},${S},${S},${S},${S}`
| `${S},${S},${S},${S},${S},${S}`
If you hover over Amaze, you will see the type reported as:
type Amaze = S | "cool,cool" | "cool,wow" | "cool,biz" | "cool,sweet"
| "cool,yowza" | "cool,fantastic" | "wow,cool" | "wow,wow"
| "wow,biz" | "wow,sweet" | "wow,yowza" | "wow,fantastic"
| ... 55967 more ...| "fantastic,fantastic,fantastic,fantastic,fantastic,fantastic"
See typescript playground
Notice that ... 55967 more .... Amaze is now a union with over fifty five thousand possible values. This may affect performance in your IDE at this point. And if you add the version that takes 7 strings you'll get a type error:
Expression produces a union type that is too complex to represent.(2590)
Eventually typescript cuts you off for performance sake. But again, for small lists, this may be viable.
You can't.
Typescript can type strings which can have any content, or can it can type exact strings like "cool" or "wow". But typescript will never know about if a string contains certain characters.
The only way to make this work would be to store these as an array instead:
type AmazeArray = AcceptableVal[];
const dabes: AmazeArray = ['cool', 'wow'];
with new template string feature of ts4.1 you can do this using following utils
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void
? I
: never;
type UnionToOvlds<U> = UnionToIntersection<U extends any ? (f: U) => void : never>;
type PopUnion<U> = UnionToOvlds<U> extends (a: infer A) => void ? A : never;
type UnionConcat<U extends string, Sep extends string> = PopUnion<U> extends infer SELF
? SELF extends string
? Exclude<U, SELF> extends never
? SELF
:
| `${UnionConcat<Exclude<U, SELF>, Sep>}${Sep}${SELF}`
| UnionConcat<Exclude<U, SELF>, Sep>
| SELF
: never
: never;
example
type Keys = "a" | "b" | "c";
type Test = UnionConcat<Keys, ",">
// Test = "a" | "b" | "c" | "a,b" | "a,c" | "b,c" | "a,b,c"
type Test2 = UnionConcat<Keys, "-">
// Test2 = "a" | "b" | "c" | "a-b" | "a-c" | "b-c" | "a-b-c"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With