Tooltip for mapped type displays number key instead of string #47214
Copy link
Copy link
Closed
Labels
Not a DefectThis behavior is one of several equally-correct optionsThis behavior is one of several equally-correct options
Description
Bug Report
Unlikely this hasn't been already mentioned before, but i couldn't find anything.
A mapped type using string keys which represent numbers displays these as numbers in the tooltip.
type A = { [K in '0']: number }; // { 0: number }
type B = { '0': number }; // { '0': number }
type C = { 0: number }; // { 0: number }
type Atest = '0' extends keyof A ? 'yes' : 'no'; // 'yes'🔎 Search Terms
mapped type tooltip displays number string key
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about #common-bugs-that-arent-bugs
⏯ Playground Link
Playground link with relevant code
🙁 Actual behavior
Tooltip displays
type A = {
0: number;
}
🙂 Expected behavior
Tooltip displays
type A = {
'0': number;
}
PS: I'd prefer it even more, if TS stopped allowing keys being some subtype of number altogether, but i guess that's a different topic.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Not a DefectThis behavior is one of several equally-correct optionsThis behavior is one of several equally-correct options
Activity
MartinJohns commentedon Dec 21, 2021
I would expect
{ '0': number }to show{ 0: number }. But in the end these two types are absolutely the same.ASDFGerte commentedon Dec 21, 2021
As javascript object initializers, they are identical. Typescript types, for what i'd assume are legacy reasons, differentiate between the two:
MartinJohns commentedon Dec 21, 2021
That's interesting. I wonder if that's intentional. The object types are identical.
(Note the
// ^?, it will inline show the type above the caret. Neat little feature.)ASDFGerte commentedon Dec 21, 2021
The root issue is, that while javascript only has
stringandsymbolproperties, typescript allows properties to additionally have any subtype ofnumber. It then does a lot of magic (like the types extending each other) to ignore this extra again, which unsurprisingly sometimes fails. This imho causes a lot of issues, and i'd think it wouldn't really be necessary anymore, now that template string types are powerful enough (would need some work, for e.g.declare const x: { [prop: `${number}`]: number }; x[0] = 0;not giving implicitanyerrors, while e.g.x['0'] = 0works, but that doesn't look terribly difficult, compared to other things). That's only a guess though, without knowing the full picture.PS: The
// ^?is nice, i'll try remember that for future snippets.RyanCavanaugh commentedon Jan 4, 2022
Type display generally tries to use the "original spelling" of the type whenever possible (example:
B), literally just pulling whatever text you have in the sourcefile into the display text. When a type is the computed result of an immediately-evaluable operation, asAis, then there is no "original spelling" and you get the normalized form.'0"isn't quoted here the same reason a property name that doesn't look like a number gets quoted.ASDFGerte commentedon Jan 5, 2022
Thanks, so i guess the tooltip just accidentally helped me differentiate between
stringandnumberkeys sometimes. I had thought that was intended, to help notice what type a type's key was. Object property keys potentially being some subtype ofnumberhas thrown me off on multiple occasions. Guess I'll have to continue checking by writing a temporary conditional type, when i want to know. Although rare, it is relevant every now and then (e.g. tuples with their named string keys, narrowing variables to be a key of an exact type, ...).PS: Closing here soon, unless there are more thoughts or links related to the topic, or generally for how to deal with
numberbeing a subtype ofPropertyKey.