首页 > 解决方案 > 打字稿多态行为

问题描述

有没有办法在以下代码中分配正确的类型,以便 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[]' 类型的参数。

键入'字符串 | string[]' 不能分配给类型 'string[]'。

类型 'string' 不可分配给类型 'string[]'.ts(2345)

这个想法是能够通过喜欢['label', ['two', 'three']]和接收['label1', ['two1', 'three2']]

如果我们省略类型,这个片段就会变成正确的 JS 代码,所以我想知道是否有办法在 TS 中实现相同的结果。

标签: typescript

解决方案


您可以使用递归类型,例如此处的示例。

您尝试解决问题的问题在于,getRowCells函数的输出不仅是,string | string[]而且可能是string | string[] | (string[])[],等等......基本上是递归结构。

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

替代方法可能是函数重载,您可以在其中“告诉”打字稿编译器特定的输出作为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
     });
}

推荐阅读