Skip to content

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

Closed
@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

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions