Typescript 类型脚本获取程序类型推断
Typescript似乎严格根据字段的私有变量推断字段类型。 但是,如果getter返回类型联合(1),它不会抱怨,也不会从getter推断实际类型(2): 这是指定的/预期的行为吗 稍后编辑。请注意,Typescript 类型脚本获取程序类型推断,typescript,Typescript,Typescript似乎严格根据字段的私有变量推断字段类型。 但是,如果getter返回类型联合(1),它不会抱怨,也不会从getter推断实际类型(2): 这是指定的/预期的行为吗 稍后编辑。请注意,stricnullcheck也不会捕捉到这一点。它只会缺少初始化和setter 以下带有strictNullCheck警告的示例已修复: test('field type inference', () => { class A { x_: number; get x()
stricnullcheck
也不会捕捉到这一点。它只会缺少初始化和setter
以下带有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)
});
首先,当您拥有属性时,typescript假定从属性读取将检索上次写入该属性的值。你这个能手打破了惯例。但因为每个get/set函数本身在技术上是类型安全的,所以typescript不会注意到任何错误 其次,当您将常量指定给类型为并集的属性时,typescript会记住该并集的哪个成员应用于该范围的其余部分。事实上,你在这些getter/setter中有逻辑并不重要 这与私人财产无关,一切都与公共财产有关 假设你上了一堂非常简单的课:
// No getters/setters
class B {
x: number | undefined
}
const b = new B()
b.x // number | undefined
b.x = 1
b.x // number
正如您所看到的,typescript会记住您分配的内容,知道它不是未定义的,然后从属性的结果类型中删除它,只要它知道这是真的
现在让我们来试试这个课程:
// useless getters/setters
class C {
get x(): number | undefined {
return undefined;
}
set x(v: number | undefined ) {
// no-op
}
}
const c = new C()
c.x // number | undefined
c.x = 1
c.x // number
现在,getter/setter是无用的,但它会给您“错误”的结果
如果最后一个值是在相同的同步执行范围内设置的,则Typescript希望getter返回最后一个设置的值。事实上,大多数程序员可能也会这样做
理想情况下,编译器会在此处标记某个问题,但通过这些设置程序跟踪类型安全性实际上是一件相当复杂的事情。首先,当您拥有属性时,typescript假定从属性读取将检索上次写入该属性的值。你这个能手打破了惯例。但因为每个get/set函数本身在技术上是类型安全的,所以typescript不会注意到任何错误 其次,当您将常量指定给类型为并集的属性时,typescript会记住该并集的哪个成员应用于该范围的其余部分。事实上,你在这些getter/setter中有逻辑并不重要 这与私人财产无关,一切都与公共财产有关 假设你上了一堂非常简单的课:
// No getters/setters
class B {
x: number | undefined
}
const b = new B()
b.x // number | undefined
b.x = 1
b.x // number
正如您所看到的,typescript会记住您分配的内容,知道它不是未定义的,然后从属性的结果类型中删除它,只要它知道这是真的
现在让我们来试试这个课程:
// useless getters/setters
class C {
get x(): number | undefined {
return undefined;
}
set x(v: number | undefined ) {
// no-op
}
}
const c = new C()
c.x // number | undefined
c.x = 1
c.x // number
现在,getter/setter是无用的,但它会给您“错误”的结果
如果最后一个值是在相同的同步执行范围内设置的,则Typescript希望getter返回最后一个设置的值。事实上,大多数程序员可能也会这样做
理想情况下,编译器会在此处标记某个问题,但通过这些设置程序跟踪类型安全性实际上是一件相当复杂的事情。您可能没有将
strictNullChecks
作为编译器选项启用,在这种情况下,TS会从联合中删除所有未定义的/null
类型。我想我会,但是为什么这很重要呢?因为strictNullCheck只是将可能的null解引用视为错误,而在这里,它并没有推断实际的类型。也就是说,这张支票没有什么可抓的。strictNullCheck将捕获的唯一一件事是,我需要一个构造函数来初始化x_3;。但是,如果我确实添加了构造函数,它将不会捕捉到这一点,因为这是一个推理问题。strictNullChecks
不会捕捉构造函数中缺少的初始化,这就是strictPropertyInitialization
的目的。如前所述,如果未设置strictNullChecks
,则TypeScript只会从任何类型联合中删除undefined
(请验证是否已启用)。getter/setter对的类型必须相同,但完全独立于私有字段x
。我理解。然而,在实践中,确实如此。我在strictNullCheck
中看到的两个错误可能是通过以下方式解决的:set x(v:number | undefined){this.x_=+(v??0);}和missing构造函数,通过` constructor(value:number){this.x_=value;}解决的。`尽管如此,我还是要更新帖子来澄清哦,我明白了!实际上,这看起来像是流类型中的一个bug/限制,其中对a.x
的赋值被假定为赋值到x
时读取的值,但是对于getter/setter,这显然是不合理的缩小行为!您可能可以在TypeScript Github repo中找到此行为的问题报告。您可能没有将strictNullChecks
作为编译器选项启用,在这种情况下,TS会从联合中删除所有未定义的/null
类型。我想是的,但是为什么这很重要呢?因为strictNullCheck只是将可能的null解引用视为错误,而在这里,它并没有推断实际的类型。也就是说,这张支票没有什么可抓的。strictNullCheck将捕获的唯一一件事是,我需要一个构造函数来初始化x_3;。但是,如果我确实添加了构造函数,它将不会捕捉到这一点,因为这是一个推理问题。strictNullChecks
不会捕捉构造函数中缺少的初始化,这就是strictPropertyInitialization
的目的。如前所述,如果未设置strictNullChecks
,则TypeScript只会从任何类型联合中删除undefined
(请验证是否已启用)。getter/setter对的类型必须相同,但完全独立于私有字段x_