TypeScript: .map () для типа объединения строки [] | string [] [] вызывает ошибку - PullRequest
2 голосов
/ 09 июля 2020
interface Props {
    data: string[] | string[][];
}

function Component({ data }: Props) {
    return data.map(v => v);
}

map () выдает ошибку: это выражение не вызывается. Каждый член типа объединения '((callbackfn: (value: string, index: number, array: string []) => U, thisArg ?: any) => U []) | ((callbackfn: (value: string [], index: number, array: string [] []) => U, thisArg ?: any) => U []) 'имеет подписи, но ни одна из этих подписей не совместима с друг друга. (2349)

Почему это так и как это исправить?

Код на игровой площадке TypeScript

Ответы [ 2 ]

1 голос
/ 09 июля 2020

Сложность в том, что Array<T>.map имеет тип объединения, а именно:

function foo({ data }: Props) {
  // x has the type:
  // (<U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]) | 
  // (<U>(callbackfn: (value: string[], index: number, array: string[][]) => U, thisArg?: any) => U[])
  let x = data.map;
}

Это объединение функций , а не функция с объединенными параметрами.

Если бы определение было примерно таким:


function otherMap<U>(
  data: string[] | string[][],
  callbackfn:
    (value: string | string[], index: number, array: string[] | string[][]) => U,
  thisArg ?: any
): U[] {
  // ...
}

Вы можете использовать защиту типа или определить функцию, которая делает именно то, что вы хотите, вместо использования Array.map.

Тип защитного ограждения следующий:


function bar({ data }: Props) : string[] | string[][] {
  if (isMultiDimArray(data)) {
    return data.map(z => z);
  }

  return data.map(z => z);
}

function isMultiDimArray<T>(data: T[] | T[][]): data is T[][] {
  if (data.length == 0) return false;

  var firstItem = data[0];
  return Array.isArray(firstItem);
}
1 голос
/ 09 июля 2020

Это ограничение TypeScript. Если у вас есть объединение двух массивов:

string[] | number[]

, вы не можете вызвать любой метод на нем. Сначала вам нужно разъединить объединение.

Решение первое

interface Props {
    data: string[] | string[][];
}

function isString(arg: any): arg is string {
    return typeof arg === 'string'
}

function isStringArray(arg: any): arg is string[] {
    return Array.isArray(arg) && arg.every(isString);
}

function Component({ data }: Props) {
    if (isStringArray(data)) {
        data.map(str => str)
    } else {
        data.map(strArr => strArr);
    }
}

Решение второе

Попробуйте generi c версия.

interface Props<T> {
    data: T[];
}

function Component<T extends string | string[]>({ data }: Props<T>) {
    return data.map(v => v);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...