【问题标题】:How to access all properties when BehaviorSubject declared with multiple interfaces?使用多个接口声明 BehaviorSubject 时如何访问所有属性?
【发布时间】:2021-09-12 17:31:49
【问题描述】:

我有几个接口如下:

export interface INT1 {
   prop1: string;
   prop2: string;
}

export interface INT2 {
   prop1: string;
   prop3: string;
}

export interface INT3 {
   prop1: string;
   prop4: string;
}

现在我正在尝试声明一个返回上述三个接口之一的BehaviorSubject

private _mySub$ = new BehaviorSubject<INT1 | INT2 | INT3>(undefined);

这不起作用,因为如果我访问BehaviorSubject 值,我只能找到共享属性(在这种情况下只有prop1)。 我做错了什么?

【问题讨论】:

  • 这是应该发生的 - 如果它是这三种类型中任何一种的主题,prop1 是唯一保证存在的属性。

标签: typescript generics rxjs


【解决方案1】:

代码没有问题。由于_mySub$ 可能是INT1INT2INT3 类型的BehaviorSubject,因此静态分析只能保证_mySub$ 在所有情况下都具有prop1 属性。在不缩小类型的情况下推断其他属性的存在是不正确的。

如果您知道对于特定上下文,BehaviorSubject 将始终准确返回其中一个接口,那么您可以使用更具体的声明,例如:

private _mySub$ = new BehaviorSubject<INT1>({prop1: '1', prop2: '2'});

类型保护

处理广泛类型定义的常见解决方案是使用TypeScript Type Guards

示例:INT1 的用户定义类型保护

function instanceOfINT1(object: any): object is INT1 {
  return 'prop2' in object;
}

使用类型保护,当BehaviorSubject 发出INT1 时,您可以安全地访问prop2

class MyClass {
  private _mySub$ = new BehaviorSubject<INT1 | INT2 | INT3>({prop1: '1', prop2: '2'});

  constructor() {
    this._mySub$.subscribe( (val) => {
      if (instanceOfINT1(val)) {
        console.log(`val.prop2: ${val.prop2}`);
      }
    });
  }
}

【讨论】:

    【解决方案2】:

    首先,您可以声明一个具有共享 prop1 属性的“基础”接口。

    export interface BASE {
       prop1: string;
    }
    
    export interface INT2 extends BASE {
       prop3: string;
    }
    
    export interface INT3 extends BASE {
       prop4: string;
    }
    

    其次,你可以使用 typescript 断言:

    const int3: INT3 = obj as INT3;
    

    https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-29
      • 2011-01-28
      • 2020-03-02
      • 1970-01-01
      • 2013-12-16
      相关资源
      最近更新 更多