Danny Delott
Danny Delott

Reputation: 7008

TypeScript error when passing parameters between functions

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

Answers (3)

Christoph L&#252;tjen
Christoph L&#252;tjen

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

Nurbol Alpysbayev
Nurbol Alpysbayev

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

jonrsharpe
jonrsharpe

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

Related Questions