-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New numeric string type to accurately represent numeric indexes #44649
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
I linked the old issue I created for this even though it's not relevant anymore and should be ignored since it's easier to follow for anyone watching the previous issue |
There is ongoing work to improve index signatures in #44512. That PR includes fixing index signatures with key type We don't have a predefined type to represent a string with a round-tripping numeric value, but the template literal type |
I guess to be 100% correct, only integers should be usable as indices, but thereβs probably no way to enforce that at the type level. |
Actually, there's nothing in JavaScript's automatic number-to-string conversion when indexing an object that requires integers. It's true there are optimizations for arrays that only apply for integer values, but that's really an orthogonal issue. The thing we're wanting for check for string literals used with numeric index signatures is that |
How much of this code will be possible? const a: {[prop: `${number}`]: number} = {};
a[1] = 123; // currently not allowed when using the above index type
a['2'] = 321; // also currently not allowed
let i: string = '0';
for (i in a) {
console.log(a, a[i], typeof i); // first iteration: { "1": 123, "2": 321 }, 123, "string"
// above `a[i]` doesn't work either
if (i === '1') {...}
} It's currently not possible to use the type `${number}` which means that the type of the index can't be specified in such a way that it represents a numerical string index to reflect the true value of What I'm basically asking for is some way to be more accurate in the type of the indexes in such a way that it represents my intent exactly rather than relying on a developer reading the code understanding that this is how it really behaves, I understand that I can simply use this format above where I split |
The problem with your example is that, if type safety is to be maintained, To see what I mean, take this example: let a: { [prop: number]: number }; // all numeric props with number values
const b = { 1: 1, 2: 2, "foo": "bar" };
a = b; // now `a` has a "foo" property with a string value, even though its index signature claims it's all numbers
for (const i in a) { // `i` can only safely be typed as string
const x = a[i]; // oops, what is the type of `x` here?
console.log(x); // should print 1 -> 2 -> "bar"
} |
What you're describing here is not related to my point, but it is its own issue, it shouldn't allow I didn't say that the I'm aware that it's possible for such a scenario as you've specified to happen, but that doesn't take away the need to be more concise when specifying the type, otherwise why would I even specify a type in the first place? |
This is a common misunderstanding. A numeric index signature is not a restriction on what kind of keys an object may have. It's a restriction on what type of values can exist at numerically-named property slots. |
That was my point: even if there were a |
That's not my point though, I'm not asking to change the type of I'm not even asking for This is about the intent being shown, not an indication that it's the only possible type since all types can be cheated, especially during runtime. |
If literally all you want is to have the ability to write { [n: numstring]: T } instead of { [n: number]: T } but otherwise have identical semantics, I don't think this is an in-scope suggestion. Otherwise explaining what deficits you see with |
Using const a: {[prop: `${number}`]: number} = {};
// none of these are allowed
a[`${1}`] = 123;
a[`1`] = 123;
a[1] = 123;
a['2'] = 321;
type numstring = number;
const a: {[prop: numstring]: number} = {}; // this refuses as well stating: An index signature parameter type cannot be a type alias. Consider writing '[prop: number]: number' instead. Neither potential way for specifying something at least resembling what I want to portray in the code works. That's besides the benefit that being able to use any of these formats gives: a[1] = 123;
a['2'] = 321; I'm just not specifying this benefit anymore since I'm aware of work being done to allow that right now on PR #44512 |
I ran into the issue of lacking a numeric string type just now. Here is my own motivating example. I am working with an API returning JSON data with numeric string values. URL to example data: Relevant snippet of the data: {
"desc":"LOCAL MOON STATE * MOON PHASE= 39.3 (waxing gibbous)",
"time":"2023-02-02T00:00:00-05:00",
"value":"39.279116267"
} Our logic checks whether the "value" property is less than or equal to some numbers. if (moonphase.value <= 25) {
// some logic
} else if (moonphase.value <= 50) {
// some other logic
} // and so on JavaScript is able to compare the numeric strings and numbers correctly. When I convert the code to TypeScript, I don't have a clean way of typing this property. If I declare the type to be I do not want to explicitly convert the numeric string to a number if I do not have to, as it makes the code a little more complicated. My current workaround is to declare the type to be |
These days all except the |
This was an old ticket, so I don't remember the specific use-case I needed it for, but if it's now allowing those, then it probably does solve the original issue. I most likely worked around this limitation in another way. I'll try looking at my git history for the project I was most likely working on at the time to see if I find anything that looks familiar and will see if I can figure out what I wanted to do then. |
Looks like it's still not quite working as expected. The indexes are fine, but once it's used in a loop, the type of for (const i in a) {
console.log(a, a[i], typeof i); // first iteration: { "1": 123, "2": 321 }, 123, "string"
// above `a[i]` is marked as an error
} Because |
Suggestion
π Search Terms
Object key type, numeric string type, index signature parameter type
β Viability Checklist
My suggestion meets these guidelines:
β Suggestion
A new type should be created to represent numbers in string or number format (a number can be used where this type is used, but the real type is a string representation of a numerical value).
This should be used in cases where object indexes are set to number to allow for number and string representation of said number to be used in indexing and to make it more accurate as the indexes are actually stored as strings even if the restriction is that the creation of a new index should be done with a number.
This will also help with a few other places where the type is indicated as a number, but the real type is a string.
π Motivating Example & π» Use Cases
Conciseness improvment:
This would instead be something like this (name of type is not final, I'm sure there are better names this can have)
This will also be useful in a similar way when looping through an array as the indexes are also treated as strings.
And another benefit outside of this will be to allow for string representation of numbers to be better defined as such in general
The text was updated successfully, but these errors were encountered: