Dinoiam
Dinoiam

Reputation: 23

How to fix TS Error inside a function that has parameter with multiple types?

I have a function that will be called with two possible types of parameters, both of them have a property id which is a string, and a value that can be different from each type. Inside this function, I need to call another one anyFunction. I used generics in order to return the same type of input params but when I try to call it like in the example below I got this error. I don't know how to tell TS that both the argument will be of the same type.

type Args = {
  first: [{
    id: string
    value: string
  }]
  second: [{
    id: string
    value: string
  }]
}
type Args2 = {
  first: [{
    id: string
    value: number
  }]
  second: [{
    id: string
    value: number
  }]
}

function anyFunction<T>(
  list1: Array<T> = [],
  list2: Array<T> = [],
): Array<T> {
  //do things
  return [...list1, ...list2];
}

function myFunction({ first, second }: Args | Args2) {
  anyFunction(first, second) <-- error
}

TS Error

Argument of type '[{ id: string; value: string; }] | [{ id: string; value: number; }]' is not assignable to parameter of type '{ id: string; value: string; }[] | undefined'.
  Type '[{ id: string; value: number; }]' is not assignable to type '{ id: string; value: string; }[]'.
    Type '{ id: string; value: number; }' is not assignable to type '{ id: string; value: string; }'.
      Types of property 'value' are incompatible.
        Type 'number' is not assignable to type 'string'.

Upvotes: 1

Views: 91

Answers (1)

jsejcksn
jsejcksn

Reputation: 33748

You can use generics to make it easier to create variations of your Args types — and then use those again in your function's generic type parameters:

TS Playground

type Id = { id: string };
type Value<T> = Id & { value: T };

type StrValue = Value<string>;
type NumValue = Value<number>;

type Args<T> = Record<'first' | 'second', T>;

type Args1 = Args<[StrValue]>;
type Args2 = Args<[NumValue]>;

function concatenate <T>(
  list1: T[] = [],
  list2: T[] = [],
): T[] {
  return [...list1, ...list2];
}

function myFunction <
  ValueType extends StrValue | NumValue,
  T extends Args<[ValueType]>,
>({first, second}: T): void {
  const result = concatenate(first, second);
  console.log(result);
}


// Use:

const args1: Args1 = {
  first: [{id: '1.1', value: '1.1'}],
  second: [{id: '1.2', value: '1.2'}],
};
myFunction(args1); // ok

const args2: Args2 = {
  first: [{id: '2.1', value: 2.1}],
  second: [{id: '2.2', value: 2.2}],
};
myFunction(args2); // ok

Upvotes: 1

Related Questions