Reputation: 31
I'm trying to create a type for array's functions in a way that it can return different type depending on wether input array is empty or not.
I tried to use conditional type in combination with tuples
First try:
export const lastElement = <T, U extends T[]>(array: U): U extends [T, ...T[]] ? T : null => {
return array[array.length - 1]
}
The code above returns the following error:
Type 'T' is not assignable to type 'U extends [T, ...T[]] ? T : null'.ts(2322)
array.ts(343, 29): This type parameter might need an extends U extends [T, ...T[]] ? T : null constraint.
It looks like for some reason TS doesn't try to check condition and just assign return type to the whole expression
Second try:
export const lastElement = <T, A extends T | null, U extends [A, ...T[]]>(array: U): A extends null ? null : T => {
return array[array.length - 1]
}
The code above returns the following error:
Type 'T | A' is not assignable to type 'A extends null ? null : T'.
Type 'T' is not assignable to type 'A extends null ? null : T'.
Again it looks like the TS doesn't understand that there is a condition in return type
Question
Is it possible to use condition types on typles in type script? Is there a way to make a condition on an element of a tuple?
Upvotes: 2
Views: 431
Reputation: 23825
I am not really sure why you tried to have two or even three generic types. There is only one parameter. So one generic type should be enough.
Having multiple generic types messed up your inference in both examples. So let's just have a single generic type T
which has to be an array. Let's also use the variadic tuple syntax to let TypeScript infer T
as a tuple instead of an array.
export const lastElement = <
T extends any[]
>(array: [...T]): T extends [...any[], infer U] ? U : null => {
return array[array.length - 1]
}
In the conditional, we infer the last element of T
and return it if it exists.
lastElement([]) // null
lastElement(["abc", new Date(), 3]) // number
Upvotes: 2