简体   繁体   English

Typescript getter 类型推断

[英]Typescript getter type inference

Typescript seems to be inferring field types strictly based on the private variable of a field. Typescript 似乎严格根据字段的私有变量推断字段类型。 However, it won't complain if the getter returns a type union (1), nor will it infer the actual type from the getter (2):但是,如果 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'
})

Is this specified / expected behavior?这是指定/预期的行为吗?

Later edit.后来编辑。 Note that strictNullCheck will not catch this either.请注意, strictNullCheck也不会捕捉到这一点。 The only two it will are missing initialization and setter唯一缺少初始化和设置器的两个

The following example with strictNullCheck warnings fixed:以下示例修复了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)
});

Firstly, when you have properties typescript assumes that reading from the property will retrieve the value last written to that property.首先,当您拥有属性时,打字稿假定从属性读取将检索最后写入该属性的值。 You getter/setter here breaks that convention.你在这里的 getter/setter 打破了这个约定。 But because each get/set function is technically typesafe on it's own, typescript doesn't notice anything wrong.但是因为每个 get/set 函数在技术上都是类型安全的,所以 typescript 不会发现任何错误。

Second, when you assign a constant to a property typed as a union, typescript remembers which member of that union applies for the rest of that scope.其次,当您将常量分配给类型为联合的属性时,打字稿会记住该联合的哪个成员适用于该范围的其余部分。 The fact you have logic in those getters/setters doesn't matter.你在这些 getter/setter 中有逻辑的事实并不重要。

It's got nothing to do with the private property, and everything to do with the public one.它与私有财产无关,而与公共财产有关。

Let's say you had this very simple class:假设您有一个非常简单的类:

// No getters/setters
class B {
  x: number | undefined
}

const b = new B()
b.x // number | undefined
b.x = 1
b.x // number

As you can see, typescript remembers what you've assigned, knows it's not undefined, and then strips that from the resulting type of the property in any where it can know that to be true.如您所见,打字稿会记住您分配的内容,知道它不是未定义的,然后从属性的结果类型中删除它可以知道的任何地方。


Now let's try this class:现在让我们试试这个类:

// 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

Now the getters/setters are useless, but it gives you the "wrong" results.现在 getter/setter 没用了,但它给了你“错误”的结果。

Playground 操场


Typescript expects a getter to return the last set value if that last value was set in the same synchronously executed scope.如果最后一个值是在同一个同步执行范围内设置的,Typescript 期望 getter 返回最后一个设置值。 In fact most programmers probably would, too.事实上,大多数程序员也可能会这样做。

Ideally the compiler would flag an issue with something here, but tracing the type safety through these setters is actually a pretty complex thing to do.理想情况下,编译器会在这里标记某个问题,但通过这些 setter 跟踪类型安全实际上是一件非常复杂的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM