Bug报告
🔎 搜索词
控制流分析,解构赋值
🕗 版本与回归信息
这个已经存在了,但我认为在4.6中引入这个功能时可能已经修复了。
⏯ Playground链接
带有相关代码的Playground链接
💻 代码
export const reduce = <S, T extends S>(self: Iterable<T>, operation: (acc: S, t: T) => S): S => {
const iter = self[Symbol.iterator]();
let { value, done }: IteratorResult<T, unknown> = iter.next();
if (done) throw new Error("Empty iterable can't be reduced.");
let acc: S = value; // Type 'unknown' is not assignable to type 'S'.
while (!done) {
acc = operation(acc, value);
({ value, done } = iter.next());
}
return acc;
};
请注意,如果你不向上转型 iter.next()
,你将不会得到错误,但这并不是出于好的原因:
let {value, done} = iter.next(); // type is IteratorResult<T, any>
if (done) throw new Error("Empty iterable can't be reduced.");
// value is any and can be assigned to anything
一个更小的仓库是:
export function foo(iter: Iterator<number, string>) {
let { value, done } = iter.next();
if (done) return;
let acc: number = value; // Type 'string | number' is not assignable to type 'number'. Type 'string' is not assignable to type 'number'.
return acc;
}
🙁 实际行为
上面最后一个例子中的 value
被推断为 number | string
,它应该是 number
🙂 预期行为
我希望有与没有解构相同的推断:
export const reduce2 = <S, T extends S>(self: Iterable<T>, operation: (acc: S, t: T) => S): S => {
const iter = self[Symbol.iterator]();
let result: IteratorResult<T, unknown> = iter.next();
if (result.done) throw new Error("Empty iterable can't be reduced.");
let acc: S = result.value; // result.value is T (extends S)
while (!result.done) {
acc = operation(acc, result.value);
result = iter.next();
}
return acc;
};
4条答案
按热度按时间wdebmtf21#
: IteratorResult<T, unknown>
部分,它就可以正常工作了。iswrvxsc2#
好的,对不起,我会填写它。但是,留下
IteratorResult<T, unknown>
的bug并没有被修复,请参阅我的最后一条评论,它只是不会报错,因为它被推断为任意类型,而不是未知类型(默认情况下第二个泛型参数是任意类型)。你也可以尝试:
hmtdttj43#
我还有一个例子:
@RyanCavanaugh@MartinJohns
q5iwbnjs4#
A较短的
const
与let
。示例取自#46266。