Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript creating Set/Array from array of numbers or strings

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
like image 814
Mero Avatar asked Nov 09 '21 23:11

Mero


People also ask

How do I turn an array of numbers into an array of strings?

To convert an array of numbers to an array of strings, call the map() method on the array, and on each iteration, convert the number to a string. The map method will return a new array containing only strings. Copied! const arrOfNum = [1, 2, 3]; const arrOfStr = arrOfNum.

How do you convert a string of numbers to an array of numbers?

You can convert a String to integer using the parseInt() method of the Integer class. To convert a string array to an integer array, convert each element of it to integer and populate the integer array with them.

Should I use [] or array in TypeScript?

There is no difference at all. Type[] is the shorthand syntax for an array of Type . Array<Type> is the generic syntax. They are completely equivalent.

How do you create an array in typescript?

1. Creating an Array. Like JavaScript, TypeScript has an Array type to allow the assignment of multiple values. The array is specified by adding a square bracket after the type. To use the type-safety capability of TypeScript, we can add diamond brackets to specify the type of the elements in the array.

How do you assign multiple values in typescript?

Like JavaScript, TypeScript has an array type to allow assignment of multiple values. The array is specified by adding a square bracket after the type. Every time a new value is added to an array, the compiler checks for type compatibility and alerts if there is a type mismatch.

How to use diamond brackets in typescript for array types?

The array is specified by adding a square bracket after the type. To use the type-safety capability of TypeScript, we can add diamond brackets to specify the type of the elements in the array. Every time a new value is added to such a generic array, the compiler checks for type compatibility and alerts if there is a type mismatch.

How do you check if an array is type safe typescript?

To use the type-safety capability of TypeScript, we can add diamond brackets to specify the type of the elements in the array. Every time a new value is added to such a generic array, the compiler checks for type compatibility and alerts if there is a type mismatch.


Video Answer


3 Answers

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.

like image 139
Jayce444 Avatar answered Oct 20 '22 21:10

Jayce444


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[])];
}
like image 1
udalmik Avatar answered Oct 20 '22 21:10

udalmik


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.

like image 1
bpoc Avatar answered Oct 20 '22 22:10

bpoc