Skip to content

Storing a keyof to a string quoted number key produces TS2344: invalid constraint in declaration file #37292

@rsesek

Description

@rsesek

TypeScript Version: 3.8.3 and 3.9.0-dev.20200309

Search Terms: [keyof quote], [keyof number declaration], [key number], [key quote], [object key number declaration]

Code

// test.ts
class C {
    readonly lines = {
        '1': 'abc',
        '2a': 'def'
    }
}

class Ref<T extends keyof C['lines']> {
    private _key: T;
    private _c = new C();

    constructor(key: T) {
        this._key = key;
    }

    value(): C['lines'][T] {
        return this._c.lines[this._key];
    }
}

const r1 = new Ref('1');
const r2 = new Ref('2a');

Expected behavior:

  1. Run tsc --declaration test.ts
  2. Run npx tsc --noEmit test.d.ts
  3. No error is emitted

Actual behavior:
Step (2) actually produces an error:

  1. Run npx tsc --noEmit test.d.ts
test.d.ts:13:23 - error TS2344: Type '"1"' does not satisfy the constraint '1 | "2a"'.

13 declare const r1: Ref<"1">;

When examining the output, note the two lines marked "BUG": the key in the lines object for 1 has been converted to number, but the Ref<"1"> is trying to access the key as a string.

// test.d.ts
declare class C {
    readonly lines: {
        1: string;     // BUG
        '2a': string;
    };
}
declare class Ref<T extends keyof C['lines']> {
    private _key;
    private _c;
    constructor(key: T);
    value(): C['lines'][T];
}
declare const r1: Ref<"1">;   // BUG
declare const r2: Ref<"2a">;

When tsc un-quotes the numeric key in C's definition, the Ref<"1"> produces a type mismatch.

Playground Link: Playground Link

Related Issues:

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions