Conditional type with generic and object works fine, for example:
interface Bar<T extends Record<string, any>> {
x: T extends { x: number } ? number : string,
y: T extends { y: number } ? number : string,
z: T extends { z: number } ? number : string,
}
const bar: Bar<{x: 1, y: 2, z: ""}> = {
x: 1,
y: 2,
z: 3 // expected error, z supposed to be a string
}
How can I apply the same principle with generic type of array? That said, how can I check if the generic includes a value or not? I want something like
interface Foo<T extends number[]> {
x: T includes 1 ? number : string,
y: T includes 2 ? number : string,
z: T includes 3 ? number : string,
}
const foo: Foo<[1,2]> = {
x: 1,
y: 2,
z: ""
}
But obviously T includes x is not a valid TypeScript syntax. Is this even possible?
I already tried with:
x: T includes 1 ? number : string,
x: T includes [1] ? number : string,
x: T includes Array<1> ? number : string,
None of them works
I can get close to what I want by checking for specific values at specific indexes of the type argument using T[0] extends 1 and similar:
interface Foo<T extends number[]> {
x: T[0] extends 1 ? number : string,
y: T[1] extends 2 ? number : string,
z: T[2] extends 3 ? number : string,
}
const foo: Foo<[1,2]> = {
x: 1,
y: 2,
z: 3 // expected error, the type argument doesn't have a number at index 2, so `z` is type string
}
const foo2: Foo<[1,2,4]> = {
x: 1,
y: 2,
z: 3 // expected error, the type argument has 4 at index 2, not 3, so `z` is type string
}
But that's order-dependent. Can I do that without having it be order-dependent? So z must be number only if the type argument has 3 anywhere in it, and string otherwise?
Tisextends number[], so the entries inThave to be numbers. When would you expect to letx,y, orzbe strings instead?[1, 2]contains the value1anywhere in it, I'm 99% sure you can't do that in the type system. You could test individual elements of the type parameter, but order would be important.1 | 2?