Issue
For example, I have a literal string union type:
type AllowedColor = 'red' | 'blue';
And I'm receiving the color from the server.
let colors = getColorsFromServer();
I want to filter the array to only consist of AllowedColor
type. This is a pseudo code that is not working:
colors.filter(color => color is AllowedColor);
Is there a way to do this?
Solution
Type aliases don't exist at runtime
You can't use a type alias in any runtime logic because of type erasure. type AllowedColor
will not exist in the generated Javascript.[1] Typescript types have only one role: static type checking logic.
You have to approach it from the other direction
type derived from a const array
Instead of runtime logic or data depending on static type information, have static type information depend on runtime data:
// values available at runtime
const allowedColors = ['red', 'blue', 'green'] as const
// type available at compile time, equivalent to:
// type AllowedColor = 'red' | 'blue' | 'green'
type AllowedColor = typeof allowedColors[number]
defining a Typescript type guard
You could then define a convenient isAllowedColor
validation function that serves double-duty as a Typescript type guard:
function isAllowedColor(color:string): color is AllowedColor {
return (allowedColors as unknown as string[]).includes(color)
}
type derived from an enum
If an allowedColors
enum
would be more useful than the array above:
// values available at runtime
enum allowedColors {red = 'red', blue = 'blue', green = 'green'}
// type available at compile time, equivalent to
// type AllowedColor = 'red' | 'blue' | 'green'
type AllowedColor = typeof allowedColors[keyof typeof allowedColors]
// a validation function that also acts as a Typescript type guard
function isAllowedColor(color:string): color is AllowedColor {
return color in allowedColors
}
usage
let someColors = ['red', 'blue', 'chartreuse', 'teal', 'ocher']
// because isAllowedColor is also a type guard, we are using the version
// of Array<T>.filter that accepts a type guard predicate, with a return
// type of T[], in this case AllowedColor[]
let filteredColors: AllowedColor[] = someColors.filter(isAllowedColor)
console.log(filteredColors) // [ 'red', 'blue' ]
Answered By - Inigo
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.