Exploring the different varieties, let's dive into some types we encounter.
array: readonly ["foo"] | readonly ["bar"] | readonly ["bar", "baz"]
When using the include
method on a T[]
, it requires an argument of type T
, matching the list's correct type. In Typescript, questioning whether a string is within an array of integers is considered ill-typed due to its likelihood of being mistakenly written in the first place.
This isn't just an ordinary array; it's a union. To invoke a method on a union, that method must be compatible with all options within the union.
The array ["foo"
] has an include
method accepting a "foo"
as its argument (representing a literal string "foo"
). Similarly, the array ["bar"
] supports an include
method expecting a "bar"
argument, and the array ["bar", "baz"
] includes an include
method for elements of the type "bar" | "baz"
.
However, since it's uncertain which specific option exists within the union, the include
call must accept input valid for all three variations. Hence, the argument should belong to the intersection type:
"foo" & "bar" & "baz"
No single string is fitting for all these conditions, rendering this type uninhabited or effectively never
. As a result, calling include
in a type-safe manner becomes unfeasible.
You may resort to any
-casting to work around such constraints, albeit sacrificing type safety. Alternatively, preserving type integrity proves more beneficial. Instead of relying solely on Typescript's highly-specific inference, explicitly declare the type you desire:
array : readonly Word[]
This declaration actually serves as a valid supertype encompassing the previously mentioned options. By providing an explicit type hint through annotation, like so:
const array: readonly Word[] = schema[schemaKey]
It's important to note that this adjustment does not entail a typical cast instructing the type system to stay quiet. The declared readonly Word[]
remains a legitimate supertype compared to the inferred literal union type. Therefore, this code passes validation while upholding type safety, requiring nothing but clarity regarding our intentions to aid the compiler.