Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract<keyof T, string> breaks inference for deep keys. #29692

Closed
FrogTheFrog opened this issue Feb 1, 2019 · 1 comment
Closed

Extract<keyof T, string> breaks inference for deep keys. #29692

FrogTheFrog opened this issue Feb 1, 2019 · 1 comment
Assignees
Labels
Needs Investigation This issue needs a team member to investigate its status.

Comments

@FrogTheFrog
Copy link

TypeScript Version: 3.4.0-dev.20190201

Search Terms:
Extracting string from key breaks inference;
Extract<keyof T, string> breaks inference;
Extract<keyof T, string> breaks inference for deep keys;

Code

interface DeepObject {
    [k1: string]: {
        [k2: string]: any
    };
}

type keys2broken<O extends DeepObject, K1 extends keyof O> =
    O[K1] extends object ? Extract<keyof O[K1], string> : never;

type keys2working<O extends DeepObject, K1 extends keyof O> =
    O[K1] extends object ? keyof O[K1] : never;

type keys2workaround<O extends DeepObject, K1 extends keyof O> =
    Extract<O[K1] extends object ? keyof O[K1] : never, string>;

interface Foo extends DeepObject {
    "a": {
        "1": 123;
        "2": string;
        "3": boolean;
    };
}

class Bar<O extends DeepObject>{
    broken<
        K1 extends keyof O,
        K2 extends keys2broken<O, K1>,
        V extends O[K1][K2]
    >(k1: K1, k2: K2, value: V) {
    }

    working<
        K1 extends keyof O,
        K2 extends keys2working<O, K1>,
        V extends O[K1][K2]
    >(k1: K1, k2: K2, value: V) {
    }

    workaround<
        K1 extends keyof O,
        K2 extends keys2workaround<O, K1>,
        V extends O[K1][K2]
    >(k1: K1, k2: K2, value: V) {
    }
}

const bar = new Bar<Foo>();
bar.broken("a", "1", true); // broken - 2nd argument is of type "1" | "2" | "3".
bar.working("a", "1", true); // ok - true is not allowed
bar.workaround("a", "1", true); // ok - true is not allowed

Expected behavior:
bar.broken("a", "1", true); should infer type "1".

Actual behavior:
bar.broken("a", "1", true); infers type "1" | "2" | "3".

Playground Link:
some smart text, a.k.a. bad sense of humour

Related issues:
#25065

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Feb 5, 2019
@jack-williams
Copy link
Collaborator

This is fixed in master, presumably by #30010.

weswigham added a commit to weswigham/TypeScript that referenced this issue Mar 11, 2019
weswigham added a commit that referenced this issue Mar 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Investigation This issue needs a team member to investigate its status.
Projects
None yet
Development

No branches or pull requests

4 participants