-
Notifications
You must be signed in to change notification settings - Fork 12.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Incorrectly infers Object key to be number instead of string #45170
Comments
This is the intended behavior. The meaning of declare function read<T, K extends keyof T>(a: T, k: K): T[K];
const arr = [0, 1, 2];
// Proposed: This should be made illegal, because 0 is not a string
read(arr, 0); instead of read(arr, "0"); because we equally let you write const e= arr[0]; |
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
For anyone coming back across this via search, here's some resolution I found for this issue.
This is pretty subtle. Technically the values legal to index the object are the storage representation, but JS has a quirk where it first converts non-symbols to strings via the indexing syntax. Other methods of accessing object properties don't do this, so I suppose this will always a be a footgun and not one TypeScript intends to save people from.
I'd propose that Array exotics should keep the behavior where For those looking to resolve this quirk locally, here's a small utility for getting the actual safe-to-access property keys from an object via the fantastic new template string types syntax: type PropOf<T> = { [K in keyof T]: K extends number ? `${K}` : K }[keyof T]
const obj = {1: 'One', '2': 'Two'}
// Incorrectly infers type 1|"2" instead of "1"|"2"
type KeysAsWritten = keyof typeof obj
// Correctly infers type "1"|"2"
type KeysAsStored = PropOf<typeof obj> |
Bug Report
In all recent versions of Typescript, TS may infer an object property to be a subtype of number instead of a subtype of string if that property is written in the quote-less shorthand and happens to be a numeric string (eg
{ 1: "One" }
instead of{ "1": "One" }
(these two objects being equivalent, since all non Array-exotic objects have string named literal properties and all property keys must be symbols or strings). This affects both the built inkeyof
and types with index signatures.🔎 Search Terms
Numeric string index signatures, object keys
🕗 Version & Regression Information
Has always been an issue
⏯ Playground Link
Playground Link showing keyof
Playground Link showing runtime behavior not mapping to type inference
💻 Code
Smallest example using
keyof
Example showing function runtime behavior differing from inference:
🙁 Actual behavior
TS infers non Array-exotic object numeric string keys are numbers
🙂 Expected behavior
TS should infer that all object keys are strings, even numeric strings
The text was updated successfully, but these errors were encountered: