简体   繁体   中英

What is the detail logic of type assertion in typescript?

I treat type assertion as something like Hi Compiler, I know the type of this variable better than you. Just follow me! Hi Compiler, I know the type of this variable better than you. Just follow me! .

But it seems that the compiler still has its own logic to infer the type. For example, suppose,

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

Then, 1&2 are no problem, but 3 throws a TS2352 error.

  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} }; } 

Why does type assertion begin to check other fields in 3? Does someone know its detail logic?


Updated: I created an issue in Github Microsoft/TypeScript#23698 .

Check the spec 4.16 Type Assertions , which is inspired by this answer :

In a type assertion expression of the form < T > e, e is contextually typed (section 4.23) by T and the resulting type of e is required to be assignable to T, or T is required to be assignable to the widened form of the resulting type of e, or otherwise a compile-time error occurs.

For case 1, T is assignable to e obviously.

For case 2, the widened form of e is {bid: string, labs: Object} , which T is assignable to. Notice that labs? is assignable to Object ( In fact, I am not sure about it, but this is my only possible explanation ).

For case 3, neither of above conditions is satisfied.

I see two options. Either use Partial<T> or any . When using any, YOU are responsible for making sure things will work, so use as last option.

Examples of both:

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
}

I think that the compiler doesn't recognize your value {a: 1} as type { [key: string]: any } because if you alter the line like this there is no compiler error:

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

also it is working if you define the variable like this:

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

and call it in your function:

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

Therefore I would say, that the compiler does not recognize your defined type from the labs field. The error message in this case is very misleading.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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