2

I have a JavaScript object with the following structure:

{
  "_index": 1,
  "foo": { ... },
  "bar": { ... },
  "baz": { ... },
}

That is, the object will always have one property _index with a number value, and then all the other keys (which aren't defined since its being used as a map) have a value of another, specific, object.

I have tried the following types in TypeScript

type Properties = {
  _index: number
}

type Fields = {
   // its not important what Metadata is, just that it has a type that isn't number
  [field: string]: Metadata
}

type Lookup = Properties & Fields

This works well for accessing an already created instance of Lookup in TypeScript, but I don't seem to be able to create an instance of Lookup in TypeScript.

For example, if I do this:

let lookup: Lookup = {
  _index: 1,
  foo: { ... }
}

I get the following error:

2322[QF available]: Type '{ _index: number; "foo": { ... }' is not assignable to type 'Lookup'. Type '{      _index: number; "foo": { ... }' is not assignable to type 'Fields'. Property '_index' is incompatible with index signature. Type             'number' is not assignable to type 'Metadata'

What is the best way to express this type in TypeScript?

2 Answers 2

2

Unfortunately Typescript will not let you create such objects directly. Although the type system allows you to create such a type, it is a bit inconsistent, since lookup['_index']does not actually conform to the index signature which should always return Metadata

The simplest way to create such an object is to use Object.assign

let lookup: Lookup = Object.assign({ _index: 1 }, {
    x: {}
})
Sign up to request clarification or add additional context in comments.

1 Comment

Using Object.assign that way kind of makes sense with the type Foo = Bar & Baz, create a Bar, create a Baz then merge them together to get a Foo
0

Just merge your definitions like this:

type Lookup = {[field: string]: Metadata, _index: number}

This will define an interface Lookup with definitely an index and then any other properties with the type metadata.

2 Comments

That doesn't work though right? I get Property '_index' of type 'number' is not assignable to string index type 'Metadata. You could get around that by having _index be either number or Metadata but that makes working with the object a bit harder.
Updated the answer. You were right, I had the wrong order.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.