Skip to content

Wildly unpredictable behavior for resolving number-type index expressionsΒ #57296

Closed
@rotu

Description

@rotu

πŸ”Ž Search Terms

numeric index property access

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about index signatures

⏯ Playground Link

https://www.typescriptlang.org/dev/bug-workbench/?target=9#code/PTAEAEBcEMCcHMCmkBcBRAygJgAxawFAAmiAxgDZyKikD2AdgM6Si2gqgDeBovoA2gA8UzWAEt68ALooA5KInxZAH1n0ArgFsARolgq1WhZNkAaHnyEoNOvTMO39qm8aXm+A4QAMAJJxu6sAC+XvYukOImBEEEdEwsAA4AjKAAvKz8SVIEIB4AegD8sQzMoAlYaRmySbLZuXyFxfFlAMyVtPyyDIi1OWANRXGlCQAs7Z04gji99byNQ4kArOOyAJL0AGYSYpAAnjP9c4MliQBs476cLTg49CF1h6DzJ2UA7CtJWC0A+iOLpwd8sdmgkABzjT4-P6nB5AprDACcKwAtDVYQN4YkkjgVgBqNF9OELMpJFLpDqXfgw+6EgZAA

πŸ’» Code

// @target:ES2022
declare const o : {
    [x:string]:'string'|'number'|'numstring',
    [x:number]:'number'|'numstring',
    [x:`${number}`]:'numstring'
}
const p1 = o[1]
//    ^?
const p2 = o['1']
//    ^?
const p3 = o['one']
//    ^?
const p4 = o['0x0']
//    ^?
const p5 = o['Infinity']
//    ^?
const p6 = o[`${300n}`]
//    ^?
const p7 = o['123_456']
//    ^?
const p8 = o[123_456]
//    ^?
const p9 = o['-1']
//    ^?
const p10 = o['+1']
//    ^?
const p11 = o[`${[6]}`]
//    ^?

πŸ™ Actual behavior

The inferred types of these index expressions are very unpredictable.

The indexes '1','0x0',`${300n}`, -1, +1 are inferred as `${number}`, and NOT as 'number'.
The indexes 1, 'Infinity', 123_456, are inferred as number
The indexes 'one', '123_456', '${[6]}' are inferred as string (these are understandable and not a problem)

πŸ™‚ Expected behavior

I expect:

  1. number and ${number} to catch the same cases, since (I believe) they express the same intent as object keys. Likely they should be considered a duplicate index signature in the type declaration.
  2. '1' and 1 to be treated the same since they retrieve the identical property.
  3. +1 and 0x0 to be inferred as non-numeric string, since (I think) the ${number} is supposed to be "the strings that a number may coerce to", not "the strings which are valid numeric literals". (though it's curious that strings containing binary, octal, and hex literals are accepted by the template string but NOT digit separators '123_456')
  4. Possibly ${300n} to be inferred as a non-numeric string. It's odd that it is treated as the string literal "300" in the index but a non-literal string when initializing a const variable.

Additional information about the issue

Originally mentioned here.

This can surely be split into multiple issues.

Metadata

Metadata

Assignees

Labels

Working as IntendedThe behavior described is the intended behavior; this is not a bug

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions