Joseph
Joseph

Reputation: 4725

Typescript yells me that 'string | T[]' is not assignable to parameter of type 'ReadonlyArray<T> '

I'm building a simple function called unique.

What this does is to remove all duplication from an array or string, so it has function overloading.

Please see this problem code example:

function unique(str: string): string[];
function unique<T>(arr: T[]): T[];

/**
 * Create an `array` without duplicates.
 */

function unique<T>(arrOrString: string | T[]): string[] | T[] {
  return [...new Set(arrOrString)]; // typescript will yell at me at this line.
}

export default unique;

enter image description here

enter image description here

However, if I change my code into if-else but actually do nothing, typescript now satisfy with this:


// same code, but actually compiling.

function unique(str: string): string[];
function unique<T>(arr: T[]): T[];

/**
 * Create an `array` without duplicates.
 */

function unique<T>(arrOrString: string | T[]): string[] | T[] {
  if (typeof arrOrString === 'string') {
    return [...new Set(arrOrString)];
  } else {
    return [...new Set(arrOrString)];
  }
}

export default unique;

Why is this happening? Do I have to write [...new Set(arrOrString)] twice in order to make it work?

Upvotes: 0

Views: 140

Answers (1)

unional
unional

Reputation: 15589

This is because the Set() constructor can't take the type string | T[].

It is actually a good thing.

Your code is serving two scenarios: when the input is string or it is T[].

Using function overloads can make your code easier to use:

function unique<T>(arrOrString: string): string[]
function unique<T>(arrOrString: T[]): T[]
function unique<T>(arrOrString: any): any {
    return [...new Set(arrOrString)];
}

const y = unique('x') // y is string[]

const p = unique([1, 2, 3]) // p is number[]

Upvotes: 1

Related Questions