Reputation: 1376
I'm trying to type a function that either accepts a string or string[] and returns either a bool or bool[] respectively. I've tried both using generics types and overload but both seem to throw some kind of error:
// generic way
function genericWay<T extends string | string[]>(val: T): T extends string ? boolean : boolean[] {
if (typeof val === 'string'){
return true // Type 'true' is not assignable to type 'T extends string ? boolean : boolean[]'
}
return [true] // Type 'true[]' is not assignable to type 'T extends string ? boolean : boolean[]'
}
const a1 = overloadWay('bbb')
const a2 = genericWay(['bbb'])
const a3 = genericWay(5333) // should throw error
// overload way
function overloadWay(val: string[]): boolean[]; // This overload signature is not compatible with its implementation signature.
function overloadWay(val: string): boolean {
if (typeof val === 'string'){
return true
}
return [true] // Type 'boolean[]' is not assignable to type 'boolean'.
}
const b1 = overloadWay('bbb')
const b2 = overloadWay(['bbb'])
const b3 = overloadWay(5333) // should throw error
Upvotes: 3
Views: 109
Reputation: 55866
Since another answer already provides with how to fix the warning in the generic way, which requires explicit type casting, here is how you can use function overloading to achive the same goals.
Your overload way definition is not correct. You need to specify all the overloads before the function and the implementing function should contain all the possible inputs and outputs in its signature. You may resort to any
in the implementation, but I do not think that's advisable wherever you can avoid.
Here is the overload way
// overload way
function overloadWay(val: string[]): boolean[];
function overloadWay(val: string): boolean ;
function overloadWay(val: string| string[]): boolean | boolean[] {
if (typeof val === 'string'){
return true
}
return [true]
}
// b1 is boolean
const b1 = overloadWay('bbb')
// b2 is boolean[]
const b2 = overloadWay(['bbb'])
// shows error
const b3 = overloadWay(5333)
Upvotes: 3
Reputation: 1542
I've applied some changes to the generic way, to have a separate Generic type, and asserted the returned value type with as
, check Here
type genType<T> = T extends string ? boolean : boolean[];
function genericWay<T extends string | string[]>(val: T): genType<T> {
if (typeof val === 'string'){
return true as genType<T>
}
return [true] as genType<T>
}
const a1 = genericWay('bbb')
const a2 = genericWay(['bbb'])
const a3 = genericWay(5333) // should throw error
Upvotes: 1