Skip to content

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

Closed
@FrogTheFrog

Description

@FrogTheFrog

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

Metadata

Metadata

Assignees

Labels

Needs InvestigationThis issue needs a team member to investigate its status.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions