Skip to content

keyof {[n: number]: any} should be string, not never #22105

Closed
@yortus

Description

@yortus

TypeScript Version: 2.8.0-dev.20180216

Search Terms:

  • keyof
  • numeric indexer

Code

// Behaviour with string keys
type StringKeys1 = {a: any, b: any, c: any};        // Specific keys only
type StringKeys2 = {[s: string]: any};              // Indexer only
type StringKeys3 = {[s: string]: any, foo: any};    // Indexer + some keys
type S1 = keyof StringKeys1;    // S1 = "a" | "b" | "c"
type S2 = keyof StringKeys2;    // S2 = string
type S3 = keyof StringKeys3;    // S3 = string

// Behaviour with numeric keys
type NumberKeys1 = {1: any, 2: any, 3: any};        // Specific keys only
type NumberKeys2 = {[n: number]: any};              // Indexer only
type NumberKeys3 = {[n: number]: any, 42: any};     // Indexer + some keys
type N1 = keyof NumberKeys1;    // N1 = "1" | "2" | "3"
type N2 = keyof NumberKeys2;    // N2 = never               <===== should be string
type N3 = keyof NumberKeys3;    // N3 = "42"                <===== should be string

Expected behavior:
N2 and N3 should be string.

Actual behavior:
N2 is never and N3 is "42".

Related Issues:
#13715 seems related but isn't really - it is asking for keyof T to allow numbers.

#22042 has an example showing how lodash typings incorrectly produce never for objects that have numeric indexers.

Discussion:
In JavaScript, both string and numeric keys end up effectively being string keys. keyof uniformly handles string keys, numeric keys, and string indexers. Why does it ignore numeric indexers?

Metadata

Metadata

Assignees

No one assigned

    Labels

    FixedA PR has been merged for this issueSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions