Полиморфизм TypeScript c поведение - PullRequest
1 голос
/ 27 мая 2020

Есть ли способ назначить правильные типы в следующем коде, чтобы TS стал счастливым?

function getRowCells<T extends string | string[]>(rowLabels: T[]): T[] {
   return [1, 2, 3]
     .map((item, i) => {
       const labels = rowLabels[i];
       if (typeof labels === 'string') {
         return labels + item;
       }
       return getRowCells(labels);           // error here, see the description below
     });
}

Ошибка выделяет labels идентификатор со следующей ошибкой:

Аргумент тип 'T' не может быть назначен параметру типа 'string []'.

Type 'строка | string [] 'не может быть назначен типу' string [] '.

Тип' string 'не может быть назначен типу' string [] '. ts (2345)

Идея состоит в том, чтобы иметь возможность передавать что-то вроде ['label', ['two', 'three']] и получать ['label1', ['two1', 'three2']].

Если мы опускаем типы, этот фрагмент становится правильным кодом JS, поэтому мне интересно, есть ли способ достичь того же результата в ТС.

1 Ответ

1 голос
/ 27 мая 2020

Вы можете использовать рекурсивный тип, как в примере здесь .

Проблема с вашей попыткой решить проблему заключается в том, что вывод функции getRowCells не просто string | string[], а также может быть string | string[] | (string[])[], et c ... в основном рекурсивная структура.

type ValueOrArray<T> = T | Array<ValueOrArray<T>>;

function getRowCells(rowLabels: ValueOrArray<string>[]): ValueOrArray<string>[] {
   return [1, 2, 3]
     .map((item, i) => {
       const labels = rowLabels[i];
       if (typeof labels === 'string') {
         return labels + item;
       }
       return getRowCells(labels);           // no error here
     });
}

Альтернативным подходом может быть перегрузка функций, когда вы «сообщаете» спецификациям компилятора машинописного текста c вывод для string[] ввод:

function getRowCells(rowLabels: string[]): string[]
function getRowCells(rowLabels: (string | string[])[]):(string | string[])[] {
   return [1, 2, 3]
     .map((item, i) => {
       const labels = rowLabels[i];
       if (typeof labels === 'string') {
         return labels + item;
       }
       return getRowCells(labels);           // no error here either
     });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...