Tom Crockett
Tom Crockett

Reputation: 31619

How to express an object type whose values all have a certain type

Simple example:

type Bar = { x: number; y: boolean }
type Foo = { [key: string]: Bar }

const foo: Foo = {
  baz: { x: 3, y: true }
}

// This works fine
console.log(foo['baz'])

// Error: Property 'baz' does not exist on type '{ [key: string]: { x: number; y: boolean; }; }'.
console.log(foo.baz)

I want the last line to type check and the type of foo.baz should be Bar. If index signatures are not the right way to make this sort of type, what is? Is it possible?

Upvotes: 0

Views: 91

Answers (2)

Nitzan Tomer
Nitzan Tomer

Reputation: 164457

If you want to have known properties then you can do:

interface Foo2 {
    baz: Bar;
}

const foo2: Foo2 = {
    baz: { x: 3, y: true }
}

console.log(foo2.baz); // fine 

Edit

In the case that the properties are arbitrary you will have to use the type in your question and you won't be able to access the values as properties, because as you said, the keys are arbitrary and the compiler has no way of knowing if the property name you specified exists, for example you can have a typo and use bar instead of baz and the compiler won't be able to warn you about it.

Upvotes: 0

basarat
basarat

Reputation: 276363

Index signatures are like a dictionary. And to a access you need to use index. This is to make it clear at point of useage that a key not found is a valid possibility.

fix

If you know the member is always going to be there annotate it as such e.g

type Foo = { [key: string]: Bar, baz:Bar }

Upvotes: 2

Related Questions