使用逻辑分配时如何保持类型保护缩小?
How to preserve type guard narrowing when using logical assignment?
以下是重现问题的示例:
type F = () => number;
type R = {
[ x: string ]: R | F | undefined
}
const isFunc = <T extends (...args: any[]) => any>(maybe:unknown) : maybe is T => typeof maybe === "function";
const check = (i: R) => {
let tmp:R = i;
let curr = tmp["something"];
if( isFunc<F>(curr) ) return;
curr // R | undefined, expected
tmp = curr || (curr = {}); //ok, expected
tmp = curr ||= {}; //Index signature is missing in type 'F'
};
如您所见,在类型保护之后,curr
正确地缩小为 R | undefined
。之后,我将 tmp
重新分配给 curr
并将后者默认为一个空对象,如果它丢失的话。
现在,如果使用 A || A = B
方法,逻辑或左侧的 curr
将适当缩小为 R | undefined
。但是,如果我使用逻辑 OR 赋值来使意图更清楚,curr
将被推断为 R | F | undefined
。这显然会导致错误,因为 F
不可分配给 R
.
问题是 - curr
在第二种情况下失去缩小的原因是什么?
在源存储库中将此作为 issue 提交后,该行为已被确认为一个错误(更像是一个设计限制,因为在使用逻辑赋值运算符时没有进行控制流分析使用逻辑运算符短路赋值)。
以下是重现问题的示例:
type F = () => number;
type R = {
[ x: string ]: R | F | undefined
}
const isFunc = <T extends (...args: any[]) => any>(maybe:unknown) : maybe is T => typeof maybe === "function";
const check = (i: R) => {
let tmp:R = i;
let curr = tmp["something"];
if( isFunc<F>(curr) ) return;
curr // R | undefined, expected
tmp = curr || (curr = {}); //ok, expected
tmp = curr ||= {}; //Index signature is missing in type 'F'
};
如您所见,在类型保护之后,curr
正确地缩小为 R | undefined
。之后,我将 tmp
重新分配给 curr
并将后者默认为一个空对象,如果它丢失的话。
现在,如果使用 A || A = B
方法,逻辑或左侧的 curr
将适当缩小为 R | undefined
。但是,如果我使用逻辑 OR 赋值来使意图更清楚,curr
将被推断为 R | F | undefined
。这显然会导致错误,因为 F
不可分配给 R
.
问题是 - curr
在第二种情况下失去缩小的原因是什么?
在源存储库中将此作为 issue 提交后,该行为已被确认为一个错误(更像是一个设计限制,因为在使用逻辑赋值运算符时没有进行控制流分析使用逻辑运算符短路赋值)。