Reputation: 23
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
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:
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