所以我有这段代码可以找到x个子数组的所有可能组合:
const optionGroups: string[][] = [['Beer', 'Not beer'], ['1', '2', '11']];
const combinations = optionGroups.reduce((opt1, opt2) => {
return opt1.reduce((acc, option1) => {
return acc.concat(opt2.map(option2 => {
return (<string[]>[]).concat(option1, option2);
}));
}, []);
});
return combinations; // <-- This is not a string[]
但是Typescript认为返回类型是string[]
,而实际上却是string[][]
。
输出为[['1', 'Beer'], ['2', 'Beer']...]
等
我一辈子都无法弄清楚如何修复字体。您可以自己尝试一下该片段,看看。
即使强制转换也会产生错误:
类型'string []'无法转换为类型'string [] []'。类型 'string'与类型'string []'不具有可比性。
有指针吗?
答案 0 :(得分:1)
看看在这种情况下使用的Array.prototype.reduce
的类型定义(第一次调用):
reduce(callbackfn: (prev: T, curr: T) => T): T;
T
是数组元素类型。由于您的通话是在string[][]
或Array<string[]>
上进行的,因此T
是string[]
。因此,该reduce调用的返回值也必须为string[]
。因此,仅从此处的类型来看,一切似乎都是正确的。
但是,运行代码时显然不会发生什么。返回值是实际的string[][]
。调试代码时,您会看到类型实际上会在运行时更改。
这样做的原因是reduce
在不传递初始值时如何工作:
如果未提供初始值,则将使用数组中的第一个元素。
因此opt1
的第一个值将是optionGroups
和string[]
的第一个元素。然后,在运行内部代码之后,结果实际上是string[][]
。您可以通过在内部明确指定类型来轻松确认这一点:
const combinations = optionGroups.reduce((opt1, opt2) => {
const result = opt1.reduce((acc, option1) => {
return acc.concat(opt2.map(option2 => {
return (<string[]>[]).concat(option1, option2);
}));
}, <string[][]>[]);
return <any>result;
});
因此,现在的问题是result
是string[][]
,但是外部归约仍然假设先前值是string[]
(由于其静态类型)。因此,您将不得不为reduce
使用不同的类型定义,该定义允许为先前的值和当前值使用不同的类型:
reduce<U>(callbackfn: (prev: U, curr: T) => U, initialValue: U): U;
不幸的是,此处的初始值是强制性的,因此您必须通过该值。您不能在此处传递null
或什至是一个空数组,因为那样会破坏您的逻辑,因此您将不得不稍微调整一下逻辑以不同方式处理第一次迭代。例如这样的
const combinations = optionGroups.reduce<string[][]>((opt1, opt2) => {
if (opt1 === null) {
return opt2.map(option2 => [option2]);
}
return opt1.reduce((acc, option1) => {
return acc.concat(opt2.map(option2 => {
return (<string[]>[]).concat(option1, option2);
}));
}, <string[][]>[]);
}, null);
答案 1 :(得分:0)
使用外部约简将optionGroups
分解为两个元素是很奇怪的,并且是问题的根源,因为当您在没有初始状态的情况下进行约简时,假定该状态具有相同的状态。类型作为输入的元素,即string[]
。外部回调实际上返回string[][]
,但是由于内部reduce的初始状态[]
的类型被扩展为any[]
而没有给出任何隐式错误,因此未捕获到不匹配。参见this issue。启用strictNullChecks
将禁用这种不良的扩展形式,并为您提供预期的类型错误。