I'm trying to properly type a function that takes an argument and wraps it into an array, however, I can't get the typings to work properly.
function wrapInArray<T>(data:T):T extends Array<infer K>? K[]: T[]{
return Array.isArray(data)? [...data]:[data]
// ^ Type '(T & any[])[number][]' is not assignable to type 'T extends (infer K)[] ? K[] : T[]'
}
const a = wrapInArray('test') // string[]
const b = wrapInArray([1,2]) // number[]
The function works correctly, and if I try to use the function, typescript correctly infers the return type. Now I'm wondering why I'm getting an error in the function declaration itself.
TS Playground
This is due to the nature of the isArray function. It's typed like this:
isArray(arg: any): arg is any[];
So when it's true, the arg is any[] says that data is any[] but you also said it was T so you end up with T & any[]...
How about (no need for overloading and bonus, we don't have to specify what the function returns, we'll let Typescript infer that for us):
function wrapInArray<T>(data: T | T[]){ //function wrapInArray<T>(data: T | T[]): T[]
if (Array.isArray(data)) {
// (parameter) data: T[]
// T was either T | T[] but it's an array, we're left with only T[]
return [...data]
} else {
// (parameter) data: T
// data was either T | T[] but it's not an array so we're left with T
return [data] // we return [T]
}
}
const a = wrapInArray('test') // string[]
const b = wrapInArray([1,2]) // number[]
TS Playground
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With