【发布时间】:2020-09-15 20:48:59
【问题描述】:
Typescript 似乎严格基于字段的私有变量来推断字段类型。 但是,如果 getter 返回类型联合 (1),它不会抱怨,也不会从 getter (2) 推断实际类型:
test('field type inference', () => {
class A {
x_: number;
// 1: no type checking here
get x(): number | undefined {
if (this.x_ === 1) return undefined;
return this.x_;
}
set x(v: number | undefined ) {
this.x_ = +v;
}
}
const a = new A();
a.x = 1;
// 2: The inferred type is number (as of x_, instead of getter)
const x: number = a.x;
console.log(a.x) // outputs 'undefined'
})
这是指定/预期的行为吗?
稍后编辑。请注意,strictNullCheck 也不会捕捉到这一点。仅有的两个将缺少初始化和设置器
以下示例修复了strictNullCheck 警告:
test('field type inference', () => {
class A {
x_: number;
get x(): number | undefined {
if (this.x_ === 1) return undefined;
return this.x_;
}
set x(v: number | undefined ) {
this.x_ = +(v ?? 0);
}
constructor(value: number) {
this.x_ = value;
}
}
const a = new A(2);
a.x = 1;
const x: number = a.x;
console.log(a.x)
});
【问题讨论】:
-
您可能没有启用
strictNullChecks作为编译器选项,在这种情况下,TS 会从联合中删除所有undefined/null类型。 -
我想我知道,但是为什么这很重要,因为 strictNullCheck 只是将可能的 null 取消引用视为错误,而在这里,它不是 推断 实际类型。 IE。 strictNullCheck 没有什么可捕捉的。 strictNullCheck 将捕获的唯一一件事是我需要一个构造函数来初始化 x_。但是,如果我确实添加了构造函数,它不会再次捕获它,因为这是一个推理问题。
-
strictNullChecks将不会捕获构造函数中缺少的初始化,这就是strictPropertyInitialization的用途。正如我所提到的,如果未设置strictNullChecks,TypeScript 只会从任何类型联合中删除undefined(请验证是否启用)。 getter/setter 对的类型必须相同,但完全独立于私有字段x_。 -
我明白了。但是在实践中,确实如此。我在
strictNullCheck看到的两个错误可能是 indefined cast att setter 解决的:` set x(v: number | undefined) { this.x_ = +(v ?? 0); } ` 和缺少构造函数,用 `constructor(value: number) { this.x_ = value; 解决}` 不过我会更新帖子以澄清 -
哦,我明白了!实际上,这看起来像是流类型中的一个错误/限制,其中对
a.x的赋值被假定为在赋值给x时读取的值,但使用 getter/setter 绝对是不合理的缩小行为!您可能可以在 TypeScript Github 存储库中找到有关此行为的问题报告。
标签: typescript