Search code examples
typescripttype-assertion

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!.

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.


Solution

  • 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.