Typescript: 'keyof' constrained to intersection of type params ends up being constrained to 'never'

Created on 3 Dec 2016  路  3Comments  路  Source: microsoft/TypeScript

For fun, I wanted to try to see how well TypeScript 2.1 could model Svelte's component API.

interface Options<Data, Computed> {
    data?: Data
    computed?: Computed;
}

declare class Component<Data, Computed> {
    constructor(options: Options<Data, Computed>);

    get<K extends keyof (Data & Computed)>(key: K): (Data & Computed)[K];
}


let c = new Component({
    data: {
        hello: ""
    }
});

c.get("hello");
//    ~~~~~~~ error! '"hello"' is not assignable to type 'never'

Expected: No error.
Actual: The constaint of K on get appears to be 'never', and thus gives an error when calling c.get with any string.

Bug Fixed

Most helpful comment

this also should work:

declare class Component<Data, Computed> {
    constructor(options: Options<Data, Computed>);

    get<K extends keyof Data>(key: K): Data[K];
    get<K extends keyof Computed>(key: K): Computed[K];
}

All 3 comments

We currently eagerly resolve a keyof T when T is not a type variable (a type parameter or an indexed access type involving type parameters). That's probably too conservative. You can cheat and make it work by introducing an intermediate type parameter:

    get<T extends Data & Computed, K extends keyof T>(key: K): T[K];

Since T doesn't appear anywhere in the parameter list, inference will always just fall back to the constraint. But this indirection isn't quite right and shouldn't be necessary.

As I peeked through the source code, that's what I figured (I think the line was type.flags & TypeFlags.TypeParameter ? getIndexTypeForTypeParameter(<TypeParameter>type)), but I wasn't 100% sure. Thanks for clarifying!

this also should work:

declare class Component<Data, Computed> {
    constructor(options: Options<Data, Computed>);

    get<K extends keyof Data>(key: K): Data[K];
    get<K extends keyof Computed>(key: K): Computed[K];
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

weswigham picture weswigham  路  3Comments

manekinekko picture manekinekko  路  3Comments

dlaberge picture dlaberge  路  3Comments

uber5001 picture uber5001  路  3Comments

zhuravlikjb picture zhuravlikjb  路  3Comments