Description
Suggestion
🔍 Search Terms
string literal, template, complex, string literals as array
✅ Viability Checklist
My suggestion meets these guidelines:
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This feature would agree with the rest of TypeScript's Design Goals.
⭐ Suggestion
I was just experimenting with this feature #40336
As mentioned in the PR:
Beware that the cross product distribution of union types can quickly escalate into very large and costly types. Also note that union types are limited to less than 100,000 constituents, and the following will cause an error:
We can't make the string literals too complex.
If we do we get this error: Expression produces a union type that is too complex to represent.
But this error is not caused because the type we wanna check is too complex.
It's cause because IDE generates every possible literal string type.
But instead of that we can treat strings as char arrays while compering them.
So no breaking changes, everything same but we compare string literals as if they are readonly char arrays
And after achieving this string unions can become less complex.
📃 Motivating Example
For example i wanna check if a string is a HEX color
I can write something like this
type Split<S extends string, D extends string> =
string extends S ? string[] :
S extends '' ? [] :
S extends `${infer T}${D}${infer U}` ? [T, ...Split<U, D>] :
[S]
type ExtractGeneric<T extends readonly any[]> = T extends readonly (infer U)[] ? U : never
const hexChars = 'ABCDEFabcef0123456789' as const
type HexChars = ExtractGeneric<Split<typeof hexChars, ''>>
type HexColor = `#${HexChars}${HexChars}${HexChars}` | `#${HexChars}${HexChars}${HexChars}${HexChars}${HexChars}${HexChars}`
const color: HexColor = "#fff"
But this is gonna give us this error: Expression produces a union type that is too complex to represent.
Because it tries to generate every possible string literal
But TypeScript is quite capable of checking if a string is a hex color.
type Split<S extends string, D extends string> =
string extends S ? string[] :
S extends '' ? [] :
S extends `${infer T}${D}${infer U}` ? [T, ...Split<U, D>] :
[S]
type ExtractGeneric<T extends readonly any[]> = T extends readonly (infer U)[] ? U : never
const hexChars = 'ABCDEFabcef0123456789' as const
type HexChars = ExtractGeneric<Split<typeof hexChars, ''>>
type HexColor = ['#', HexChars, HexChars, HexChars] | ['#', HexChars, HexChars, HexChars, HexChars, HexChars, HexChars]
const color = "#fff" as const
type Test = Split<typeof address, ''> extends HexColor ? true : false // Result: true
Example above is able to check if a string is a hex color or not.
So if we were to treat strings as readonly char arrays while compering them, the first example above would have worked without any issue.
💻 Use Cases
This can be use for many things.
- Hex Colors
- Zip Codes
- 0x wallet addresses
- URLs
- etc.