I have object where every field is array of strings. I also have string variable that can have only values based on that arrays values in object.
Now I want to check to which array (which object field) this string belongs to. I'm doing this by simply using includes()
and code works fine, but for some reason TS is complaining. Even that certain array can have certain values, it excepts from me "never" instead. I simplified code to just show TS issue.
const demo = {
a: ['value1', 'value2'],
b: ['value3'],
} as const
let demoValue: typeof demo[keyof typeof demo][number] // possible "value1" "value2" "value3"
demoValue = 'value3' // some user interaction
const test = (parent: keyof typeof demo, value: typeof demoValue) => {
console.log(demo[parent].includes(value)) // "type 'string' is not assignable to type 'never'"
}
test('a', 'value2') // ok
test('WRONG', 'value2') // there is TS error, so ok
test('a', 'WRONG') // there is TS error, so ok
I can "fix" that by making includes(value as never)
but I feel like this is not real fix but more workaround for wrong types...
CodePudding user response:
You could use a type assertion, but in this case there is a slightly safer option. If you declare a wideList
that is an array of the union of all possible values, you can assign the union of lists to that without using as
.
const test = (parent: keyof typeof demo, value: typeof demoValue) => {
const wideList: readonly (typeof demoValue)[] = demo[parent];
console.log(wideList.includes(value));
}
Update: Just thought of another solution, you could define a functional includes
(rather than OO), which is better able to deal with unions of lists:
const includes = <T>(arr: readonly T[], x: T): boolean => arr.includes(x)
const test = (parent: keyof typeof demo, value: typeof demoValue) => {
console.log(includes(demo[parent], value))
}