Home > Software design >  TypeScript creating Set/Array from array of numbers or strings
TypeScript creating Set/Array from array of numbers or strings

Time:11-10

I'm trying to create a function, that tackes array of numbers or array of string and return Set from that array, like this:

const f = (arr: number[] | string[]): number[] | string[] => {
    return [...new Set(arr)]; 
}

And getting an error:

No overload matches this call.
Overload 1 of 2, '(iterable?: Iterable | null | undefined): Set', gave the following error. Argument of type 'number[] | string[]' is not assignable to parameter of type 'Iterable | null | undefined'. Type 'string[]' is not assignable to type 'Iterable'. The types returned by 'Symbol.iterator.next(...)' are incompatible between these types. Type 'IteratorResult<string, any>' is not assignable to type 'IteratorResult<number, any>'. Type 'IteratorYieldResult' is not assignable to type 'IteratorResult<number, any>'. Type 'IteratorYieldResult' is not assignable to type 'IteratorYieldResult'. Type 'string' is not assignable to type 'number'.
Overload 2 of 2, '(values?: readonly number[] | null | undefined): Set', gave the following error. Argument of type 'number[] | string[]' is not assignable to parameter of type 'readonly number[] | null | undefined'. Type 'string[]' is not assignable to type 'readonly number[]'. Type 'string' is not assignable to type 'number'.

I can change incoming type from number[] | string[] to (number | string)[] but it means that in array could be numbers and strings at same time, that is not what i want.

const f = (arr: (number | string)[]): (number | string)[] => {
    return [...new Set(arr)];
}

f([1,2,3]);        // ok
f(['1','2','3']);  // ok
f([1,2,'3','4']);  // ok, but should be err
f([true, {}, 1]);  // err, like it should be

CodePudding user response:

EDIT: seems like this relates to some TS config. One way is to spread the array you're making the set from and cast the return value, like so:

const f = (arr: number[] | string[]): number[] | string[] => {
    return Array.from(new Set([...arr])) as number[] | string[];
}

As udalmik says you can use any though that kinda defeats the point.

CodePudding user response:

You can get rid of this error by casting argument to any[]:

function f(arg: number[] | string[]): number[] | string[] {
    return [...new Set(arg as any[])];
}
  • Related