Reputation: 7008
This pattern is throwing the TypeScript error:
Argument of type '(string | number)[]' is not assignable to parameter of type 'string[] | number[]'
function foo(value: string | number) {
return bar([value]); // <- TypeScript error
}
function bar(valueList: string[] | number[]) {
..does something...
}
I understand this is because TypeScript compiler will see this as an array with a mix of strings and numbers.
Is there a type-safe way to accomplish this? I can only think to cast to any[]
which feels bad:
function foo(value: string | number) {
const valueList: any[] = [value];
return bar(valueList);
}
Upvotes: 4
Views: 919
Reputation: 5914
This is inspired by jonrsharpe's answer but instead of using a separate interface, it uses function overloading.
Function overloads allow us to specify multiple signatures for a single implementation: https://www.typescriptlang.org/docs/handbook/functions.html#overloads
function foo(value: string);
function foo(value: number);
function foo(value: any) {
return bar([value]);
}
function bar(valueList: number[] | string[]) {
}
Upvotes: 2
Reputation: 21971
The other answer is good (I've upvoted it), but I would personally go with
return bar([value] as string[] | number[]);
especially, if I am short on time. This does not mean that it's wrong or hackish, you are just hinting to silly (in this case) Typescript a bit.
P.S. As @paleo mentioned, this is not completely type-safe.
Upvotes: 1
Reputation: 122144
One way to do this is declaration merging; define two separate interfaces for your function (see function types), then a single implementation of it:
interface Foo {
(value: string): void;
}
interface Foo {
(value: number): void;
}
const foo: Foo = function (value) {
return bar([value]);
}
This will keep the two types separate, as only one of those interfaces can be called through at any given time.
Upvotes: 4