Reputation: 1946
I am trying to type a function that should return an array type, if the input parameter is array type, and a normal parameter otherwise. Here's my attempt:
function test<T extends number|number[]>(a: T):T extends number[] ? string[] : string {
if (Array.isArray(a)) {
return ['123', '45']
}
return '123'
}
I get an error at the return statements: Type 'string' is not assignable to type 'T extends number[] ? string[] : string'.
What I'm looking for is the following:
const a = test(3) // "a" is string type
const b = test([1,2,3]) // "b" is string[] type
Upvotes: 5
Views: 1649
Reputation: 9893
Based on this Typescript will not infer different return types based on type guards in the function. But you can define multiple function signatures like this:
function test(a: number): string;
function test(a: number[]): string[];
function test<T extends number|number[]>(a: T): string | string[]{
if (Array.isArray(a)) {
return ['123', '45']
}
let str = '123'
return str;
}
const a = test(3) //string
const b = test([1,2,3]) //string[]
Also see this issue: https://github.com/microsoft/TypeScript/issues/24929
Upvotes: 2
Reputation: 2062
Union based return types are currently not supported by typescript but there is a workaround for this kind of problem.
function test<T extends number|number[]>(a: T):T extends number[] ? string[] : string {
if (Array.isArray(a)) {
return ['123', '45'] as any
}
return '123' as any
}
See a working example here.
For more details read this issue on github
Upvotes: 0
Reputation: 33041
Just use overload your function:
function test(a: number): '123'
function test(a: number[]): string[]
function test<T extends number | number[]>(a: T) {
if (Array.isArray(a)) {
return ['123', '45']
}
return '123'
}
test(2) // '123'
test([23]) // string[]
No need in conditional types.
Upvotes: 3