打字稿中类型断言的详细逻辑是什么?

时间:2018-04-25 06:11:39

标签: typescript type-assertion

我将type assertion视为Hi Compiler, I know the type of this variable better than you. Just follow me!

但似乎编译器仍然有自己的逻辑来推断类型。例如,假设,

interface PM_MGEInfo {
    category: string;
    bid: string;
    cid?: string;
    labs?: { [key: string]: any };
}

然后,1& 2没问题,但3抛出TS2352错误。

  1. function makeMgeInfo(bid: string): PM_MGEInfo {
        return <PM_MGEInfo>{
            bid
        };
    }
    
  2. function makeMgeInfo(bid: string): PM_MGEInfo {
        return <PM_MGEInfo>{
            bid,
            labs: {}
        };
    }
    
  3. function makeMgeInfo(bid: string): PM_MGEInfo {
        return <PM_MGEInfo>{
            bid,
            // error TS2352: Type '{ labs: { poi_id: string; }; bid: string; }' cannot be converted to type 'PM_MGEInfo'.
            // Property 'category' is missing in type '{ labs: { poi_id: string; }; bid: string; }'.
            labs: {a: 1}
        };
    }
    
  4. 为什么type assertion开始检查3中的其他字段?有人知道它的细节逻辑吗?

    更新:我在Github中创建了一个问题Microsoft/TypeScript#23698

3 个答案:

答案 0 :(得分:1)

检查规范4.16 Type Assertions,其灵感来自this answer

  

在&lt;形式的类型断言表达式中。 T> e,e由T进行上下文类型化(第4.23节),并且所得到的e类型需要可分配给T,或者T需要可分配给结果类型e的扩展形式,否则编译时发生错误。

对于案例1,T显然可以分配给e

对于案例2,e的加宽形式为{bid: string, labs: Object},T可分配给。请注意,labs?可分配给Object事实上,我不确定,但这是我唯一可能的解释)。

对于案例3,上述条件均不满足。

答案 1 :(得分:0)

我看到两个选项。使用Partial<T>any。当使用any时,你负责确保一切正常,所以请用作最后一个选项。

两者的例子:

function makeMgeInfoWithPartial(bid: string): Partial<PM_MGEInfo> {
  // props are optional but only those defined by PM_MGEInfo are valid
  return {
    bid,
    labs: {a: 1}
  }
}

function makeMgeInfoWithAny(bid: string): PM_MGEInfo {
  return {
    bid,
    labs: {a: 1},
    whatever: 'also works'
  } as any
}

答案 2 :(得分:0)

我认为编译器不会将您的值{a: 1}识别为类型{ [key: string]: any },因为如果您改变这样的行,则没有编译器错误:

function makeMgeInfo(bid: string): PM_MGEInfo {
  return <PM_MGEInfo>{
    bid,
    labs: {a: 1} as {[key: string]: any}
  };
}

如果您像这样定义变量,它也可以工作:

mylabs: {[key: string]: any} = {a: 1};

并在你的函数中调用它:

makeMgeInfo(bid: string): PM_MGEInfo {
  return <PM_MGEInfo>{
    bid,
    labs: this.mylabs
  };
}

因此我想说,编译器无法从labs字段识别您定义的类型。在这种情况下的错误消息是非常误导。