29
type Foo = { [key: number]: string }

const foo: Foo = { 100: 'foo', 200: 'bar' }
const sizes: number[] = Object.keys(foo)

Gives me:

Type 'string[]' is not assignable to type 'number[]

Why does Typescript assume string[]? And what is the correct way of creating an array of numbers here?

Community
  • 1
  • 1
David Hellsing
  • 106,495
  • 44
  • 176
  • 212
  • A more detailed explanation is available in this answer (check the question for more context as well): https://stackoverflow.com/a/6066954/1364793 – Dzhuneyt Jun 28 '19 at 09:18

5 Answers5

32

All keys are strings in JavaScript - just use map:

const sizes: number[] = Object.keys(foo).map(Number);

This'll only work for numeric strings - if it's a European string involving decimals, for instance, it'll be NaN, and that never ends well.

console.log(Number("10,7"));

Or change either of your types:

const sizes: string[] = Object.keys(foo);

Or:

type Foo = { [key: string]: string };
Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
6

Object properties names are always string, if you want to convert property names to numbers on the fly, you can use map(Number):

const sizes: number[] = Object.keys(foo).map(Number);

Pay attention because, if your property name can't be converter to number, you'll get NaN in your sizes array

6

Why does Typescript assume string[]? And what is the correct way of creating an array of numbers here?

Because object property names are always strings (or, to properly explain that, are always coerced to strings), hence the default signature assumes a string[] as default type, as the intellisense even suggests:

enter image description here

Besides, you can't ensure that, at runtime, those keys will be numbers. Defining a type that strictly defines that object to have numeric keys has no effect at runtime, hence it's always safer to safely cast the values to the desired type:

const sizes: number[] = Object.keys(foo).map(Number); // beware of possible NaN here.
briosheje
  • 7,356
  • 2
  • 32
  • 54
0

Object.keys always returns an array of strings:

const obj = { prop: 'prop' };
console.log(typeof Object.keys(obj)[0]);

Keys are always strings, even numeric keys like with arrays and with your Foo object - if you use a numeric key rather than a string key, it'll be coerced to a string automatically.

I'd use [key: string] instead, because that's what the type of the keys are internally.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
0

Javascript Object has no number keys! All keys are Strings. Always.If you want to map other things to values you should use a map.

var numObj = { 1:'one', 2:'two' };
var numObjKey = Object.keys(numObj);

console.log(typeof numObjKey[0]);
console.log(typeof numObjKey.map(Number)[0]);
Paresh Barad
  • 1,544
  • 11
  • 18