打字稿多态行为

时间:2020-05-27 11:49:27

标签: typescript

是否可以在下面的代码中分配适当的类型,以使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 []'。ts(2345)

这个想法是要能够像['label', ['two', 'three']]这样通过并接收['label1', ['two1', 'three2']]

如果我们省略类型,则此代码段将成为正确的JS代码,因此我想知道是否有办法在TS中实现相同的结果。

1 个答案:

答案 0 :(得分:1)

您可以使用递归类型,例如示例here

尝试解决该问题的问题在于,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
     });
}