I’m trying to make a utility function which will take either a tuple or an array and return whichever it took. I’ve constructed a generic type which understands whether it is passed a tuple or an array, but when I try to use the generic in my utility function, the generic doesn’t detect the tuple:
type Foo = [number, number]
type MaybeFoo<T> = T extends Foo ? Foo : number[]
const bar = [1, 1, 1, 2]
const baz: Foo = [1, 1]
type WasntFoo = MaybeFoo<typeof bar> // WasntFoo is number[], which is what I want
type WasFoo = MaybeFoo<typeof baz> // WasFoo is [number, number], which is what I want
const utilityFunction = <T,>(arr: MaybeFoo<T>): MaybeFoo<T> => arr // in real life this does something to each el of arr but doesn't change the type
const r1 = utilityFunction(bar)
const r2 = utilityFunction(baz) // r2 is number[], when I want [number, number]
This is in TypeScript 4.8.4, playground here
>Solution :
This is because the TypeScript compiler can not correctly infer T in your function call. In this case the compiler defaults to unknown and as unknown does not extend Foo the type will be evaluated as number[]. If you add a typing to your function call it works as expected:
const r2 = utilityFunction<Foo>(baz)