代码之家  ›  专栏  ›  技术社区  ›  nagylzs

类型声明中的类型脚本计算机属性名,编译器错误不一致

  •  0
  • nagylzs  · 技术社区  · 7 年前

    考虑到这些类型:

    export type TSimpleFilterDict = { 
          [fieldName: string]:  (
                number | number[]  | string | boolean | null |  undefined 
           )
    };
    
    export interface IMultiFieldTextSearchSpec {
        fieldNames : string[];
        expression : string;
    };
    export type TMultiFieldTextSearch = {
        "$text" ?: IMultiFieldTextSearchSpec;
    }
    
    export type TFilterDict = TSimpleFilterDict | TMultiFieldTextSearch;
    

    如果我这样做:

    let filter : TFilterDict = {};
    filter.is_active = true;
    

    然后我得到这个编译器错误:

    [ts]
    Property 'is_active' does not exist on type 'TFilterDict'.
      Property 'is_active' does not exist on type 'TSimpleFilterDict'. [2339]
    

    但是,如果我这样做

    let filter : TSimpleFilterDict = {};
    filter.is_active = true;
    

    然后看起来很好,编译器没有给我任何错误。

    此外,这也很好:

      let filter: TSimpleFilterDict = {};
      filter.is_active = true;
      let filter2 : TFilterDict = filter;
    

    另外,如果我这样做:

        let filter : TFilterDict = {};
        filter.$text = {
            fieldNames: ["name", "address"],
            expression: "dave"
        };
    

    那就好了,根本没有警告。

    我不明白。我如何能在具有类型的变量上设置任何属性 TSimpleFilterDict ,但我不能对具有类型的变量执行相同的操作 TSimpleFilterDict | TMultiFieldTextSearch ?这看起来很疯狂!

    1 回复  |  直到 7 年前
        1
  •  1
  •   Titian Cernicova-Dragomir    7 年前

    你的“这太疯狂了!”我想说,

    天才和疯狂之间有一条很好的界限。[typescript has]删除了此行。

    如果您从工会工作的基本原理开始,那么所有的行为都是完全预期的。

    联合类型的变量可以是联合中的任一成员类型。鉴于此,我们只能安全地访问 全部的 工会会员。

    让我们看看前两个例子:

    let filter : TFilterDict = {};
    filter.is_active = true //error
    
    let filter4 : TSimpleFilterDict = {};
    filter4.is_active = true; // ok
    

    filter4 我们可以指定 is_active ,因为 TSimpleFilterDict 具有索引签名,因此我们可以分配任何属性。我们不能这样做 filter 因为,虽然 t简单筛选器dict 没有索引签名, TMultiFieldTextSearch 只有一个属性( $text )所以 is_active = true 只工作如果 滤波器 实际上是联合中的特定类型,但不适用于 任何 在联合中键入,因此typescript会引发错误。

    下一个示例:

    let filter3: TSimpleFilterDict = {};
    filter3.is_active = true;
    let filter2 : TFilterDict = filter3;
    

    这个是允许的,因为 filter3 (如上所述)具有索引签名并且分配有效。 filter2 要么可以 t简单筛选器dict t多字段文本搜索 所以我们可以分配一个 t简单筛选器dict 为了它。在分配(限制控制流分析)之后,typescript将不再确定 滤光器2 是一个 t简单筛选器dict 或A t多字段文本搜索 如此 filter2.is_active = true; 因为我们在第一个示例中得到错误的相同原因而无效。

    最后一个例子:

    let filter5 : TFilterDict = {};
    filter5.$text = {
        fieldNames: ["name", "address"],
        expression: "dave"
    };
    

    这是有效的,因为 美元文本 存在于 t多字段文本搜索 从那时起 t简单筛选器dict 使用 美元文本 也是有效的。自从 filter5.$text = { ... } 对联合中的任何类型都有效,分配有效。(尽管由于成员是在联合上访问的,其类型将为 string | number | boolean | number[] | IMultiFieldTextSearchSpec 当您尝试访问它时)

    推荐文章