9

I'm trying to create a function, that takes 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 the incoming type from number[] | string[] to (number | string)[] but it means that in the array could be numbers and strings at the 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

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

6 Comments

yes, i edit my post, last err - it's ok like it should be. I tried your code, but typeScript still make an error (
@Mero hmmm I've tried my code in TS and I don't get any errors. Which specific line is showing that error?
@Jace444 same place, at arr type in Array.from(new Set(arr)) - No overload matches this call....
Indeed, this does not solve the type error. See: typescriptlang.org/play?#code/…
@Mero ok I updated my answer, seems to be working in that playground now
|
1

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[])];
}

2 Comments

yeap, it can solve the error, but the main point is to find clear way set up incoming type as only number[] or string[] for sucure Set type, like it's not just a 1 line function. It should be possible in TS, no way we need to use hacks like this...
in and out types are exactly number[] or string[], casting to any[] is hidden inside the function
1

I think either of these might work better

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

let f1 = f([1,2,3,4,5,5,5]);
let f2 = f(['a','b','c','c','c']);
let f3 = f(['a','b','c','a','b',1,2,3,4]);//error
function f(arr:number[]):number[];
function f(arr:string[]):string[];
function f(arr:any[]):any[]{
    return [...new Set(arr)];
}

let f1 = f([1,2,3,4,5,5,5]);
let f2 = f(['a','b','c','c','c']);
let f3 = f(['a','b','c','a','b',1,2,3,4]);//error

This way the function only accepts arrays of numbers or strings but not both, and it preserves the return type information. If you pass in an array of numbers then typescript knows the return value is an array of numbers.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.