admin管理员组

文章数量:1336321

I want an index signature of type : [key: number]: string;

For example:

type MoveNbWithLocation = {     
    [key: number]: string; 
}  

Then:

const initPieceLocation: MoveNbWithLocation = {0: ''}; //This is fine
const initPieceLocation: MoveNbWithLocation = {1.3: ''}; //This is also fine
const initPieceLocation: MoveNbWithLocation = {-1: ''}; //This is NOT fine

I prefer to have a key of type 'number'.

However if there is no way to use negative numbers, maybe I have to use type 'string' for the key.

I want an index signature of type : [key: number]: string;

For example:

type MoveNbWithLocation = {     
    [key: number]: string; 
}  

Then:

const initPieceLocation: MoveNbWithLocation = {0: ''}; //This is fine
const initPieceLocation: MoveNbWithLocation = {1.3: ''}; //This is also fine
const initPieceLocation: MoveNbWithLocation = {-1: ''}; //This is NOT fine

I prefer to have a key of type 'number'.

However if there is no way to use negative numbers, maybe I have to use type 'string' for the key.

Share Improve this question asked Nov 20, 2024 at 12:55 mist777mist777 231 silver badge4 bronze badges 3
  • This is just a syntax issue, not a typing issue. Keys are always strings, so you can change that to {"-1": ""} and it will work. Note that TS recognizes "-1" as a valid numeric key anyway, as opposed to something like "a", as shown in this playground link. Does that fully address the question? If so I'll write an answer; if not, what's missing? – jcalz Commented Nov 20, 2024 at 12:58
  • Thank you both for your answers. I see how it works... @jcalz Thanks! Then I'll use 'string' type. The main reason why I preferred 'number' was to avoid parsing the string to integer. – mist777 Commented Nov 20, 2024 at 17:14
  • You can use a computed key like {[1]: ""} if you want. I'm not sure why you care about parsing strings; JS automatically converts numeric keys to strings. I've explained more in my answer. – jcalz Commented Nov 20, 2024 at 17:49
Add a comment  | 

2 Answers 2

Reset to default 2

TL;DR, coerce the number to a string like {"-1": "abc"} or use a computed key like {[-1]: "abc"}.


JavaScript objects don't actually have numeric keys. Property names are only ever strings or symbols. If you use something other that that, JavaScript will coerce it to a string. When you write a numeric literal key in an object literal like {0: ""}, this is exactly the same as if you coerced it to a string first, like {"0": ""}. There is no difference between those. And both of those are the same as if you use a computed property like {[0]: ""} or {["0"]: ""}.

That means a TypeScript numeric index signature is a bit of a convenient fiction. It actually means something like "strings of the form String(n) for some number n". A numeric index signature will accept numeric keys, but it will also accept string keys that correspond to serializing a number:

let x: MoveNbWithLocation;
x = { 1.3: "abc" }; // okay
x = { "1.3": "abc" }; //okay
x = { 1.30: "abc" }; // okay
x = { "1.30": "abc" }; // error!

The first three are all the same. The numeric literal 1.3 and the numeric literal 1.30 are the same number, and coerce to "1.3". On the other hand, the string "1.30" is not what you get for String(1.30) or String(1.3) or String(n) for any number, so it doesn't match the string index signature.

It's not obvious, but in JavaScript, there are no negative numeric literals. If you write -1, what you are actually doing is applying the unary negation operator (-) to the numeric literal 1. You are allowed to give an object literal a numeric literal key. But you are not allowed to use a negative number as a numeric literal key because there are no negative numeric literals. If you write {-1: ""}, that's a syntax error in JavaScript.

But since the key -1 and "-1" are the same, you can still get the exact same object, by either coercing it to the string yourself, or by using a computed property:

// x = { -1: "abc"}; // syntax error!
x = { "-1": "abc" }; // okay
x = { [-1]: "abc" }; // okay

And TypeScript accepts both of these as matching the numeric index signature, because they coerce to the right sort of string.

Playground link to code

You cannot use negative number in JS for indexing, that's invalid syntax so you could use template literals like this:

Playground

type T = {
    [key: `${number}`]: string;
    [key2: `-${number}`]: string;
}

const foo: T = {0: 'string'}
const bar: T = {'-0': 'string'};
const baz: T = {a: 'string'}; // error

本文标签: typescriptIs there a way to have a negative number as a key of an index signatureStack Overflow