TypeScript 中的联合类型类型推断

huangapple go评论98阅读模式
英文:

Type inference with union types in TypeScript

问题

我有一个类型C,它是A和B类型的联合。我有一个类型C的变量,在分配了B类型之后,似乎类型推断在B和C具有相同名称的属性时不起作用。

  1. class A {
  2. prop1: string;
  3. }
  4. class B {
  5. prop1: string;
  6. prop2: string;
  7. }
  8. type C = A | B;
  9. class test {
  10. thisIsC: C;
  11. constructor() {
  12. this.thisIsC = this.getTypeB(); //这不会使thisIsC被推断为B
  13. const b = this.getTypeB(); //这样可以正常工作
  14. const a = this.thisIsC;
  15. }
  16. getTypeB(): B {
  17. return new B();
  18. }
  19. }

如果属性不发生冲突,问题就不会出现,类型推断会正常工作(例如):

  1. class A {
  2. prop1: string;
  3. }
  4. class B {
  5. prop2: string;
  6. prop3: string;
  7. }
  8. type C = A | B;
  9. class test {
  10. thisIsC: C;
  11. constructor() {
  12. this.thisIsC = this.getTypeB(); //这会使thisIsC被推断为B类型
  13. const a = this.thisIsC;
  14. }
  15. getTypeB(): B {
  16. return new B();
  17. }
  18. }

我的问题是,如果我可以做一些改进类型推断的事情(与冲突的参数一起),只是告诉typescript在getTypeB()调用之后变量"thisIsC"是B类型。显然,“如果我们有一个具有联合类型的值,我们只能访问联合中所有类型的公共成员。”这对我来说有道理,但在我的代码中,“getTypeB()”明确返回B类型。我可以通过创建辅助变量或使用类型守卫进行手动类型断言来解决这个问题,但我想知道是否可以做些修改内部工作方式的事情。

Playground上的错误示例:
https://t.ly/iFZ0

提前感谢您的回答。

英文:

I have a type C which is the union of A and B types. I have a variable of type C and after assigning a B type it seems that the type infer is not working when B and C have one property with the same name.

  1. class A {
  2. prop1: string;
  3. }
  4. class B {
  5. prop1: string;
  6. prop2: string;
  7. }
  8. type C = A | B;
  9. class test {
  10. thisIsC: C;
  11. constructor() {
  12. this.thisIsC = this.getTypeB(); //This doesn't make thisIsC inferred to B
  13. const b = this.getTypeB(); //This works fine
  14. const a = this.thisIsC;
  15. }
  16. getTypeB(): B {
  17. return new B();
  18. }
  19. }

If the properties don't collide, the problem doesn't appear and the type infer is done properly (for example):

  1. class A {
  2. prop1: string;
  3. }
  4. class B {
  5. prop2: string;
  6. prop3: string;
  7. }
  8. type C = A | B;
  9. class test {
  10. thisIsC: C;
  11. constructor() {
  12. this.thisIsC = this.getTypeB(); //This makes thisIsC be inferred to B type
  13. const a = this.thisIsC;
  14. }
  15. getTypeB(): B {
  16. return new B();
  17. }
  18. }

My question is if I can do something to improve this type inference (with colliding parameters) just to tell typescript that the variable "thisIsC" is of type B after the getTypeB() call. Apparently "If we have a value that has a union type, we can only access members that are common to all types in the union." which makes sense to me, but in my code, "getTypeB()" returns explicitly a type B. I just can solve the problem creating an aux variable or doing a manual type assertion with a type guard but I want to know if I can do anything to modify how this internally works.

Playground with the error:
https://t.ly/iFZ0

Thanks in advance

答案1

得分: 1

Sure, here is the translated text:

> 我想知道我是否可以做任何修改内部工作方式的事情。

我建议对你的 AB 类型进行 标记

  1. class A {
  2. prop1: string;
  3. tag: "A";
  4. constructor() {
  5. this.prop1 = "helloworld";
  6. this.tag = "A";
  7. }
  8. }
  9. class B {
  10. prop1: string;
  11. prop2: string;
  12. tag: "B";
  13. constructor() {
  14. this.prop1 = "helloworld";
  15. this.prop2 = "prop2";
  16. this.tag = "B";
  17. }
  18. }
  19. type C = A | B;
  20. class test {
  21. thisIsC: C;
  22. constructor() {
  23. this.thisIsC = this.getTypeB();
  24. const b = this.thisIsC;
  25. b.prop2;
  26. }
  27. getTypeB(): B {
  28. return new B();
  29. }
  30. }

在对它们进行标记之后,TypeScript 能够正确地推断类型。

play

英文:

> I want to know if I can do anything to modify how this internally works.

I would recommend tagging your A and B types.

  1. class A {
  2. prop1: string;
  3. tag: "A";
  4. constructor() {
  5. this.prop1 = "helloworld";
  6. this.tag = "A"
  7. }
  8. }
  9. class B {
  10. prop1: string;
  11. prop2: string;
  12. tag: "B";
  13. constructor() {
  14. this.prop1 = "helloworld";
  15. this.prop2 = "prop2";
  16. this.tag = "B";
  17. }
  18. }
  19. type C = A | B;
  20. class test {
  21. thisIsC: C;
  22. constructor() {
  23. this.thisIsC = this.getTypeB();
  24. const b = this.thisIsC;
  25. b.prop2;
  26. }
  27. getTypeB(): B {
  28. return new B();
  29. }
  30. }

After tagging them typescript is able to properly infer the types.

play

huangapple
  • 本文由 发表于 2023年6月29日 15:40:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76578971.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定