Allyl Isocyanate
Allyl Isocyanate

Reputation: 13626

Trouble defining an object schema using Typescript

I'm working on a game, and trying to define it's schema as a set of types in Typescript:

interface Outcome {
  Difference: string,
  Room: string
};

interface Movement {
  (name: string): {
    Points: number,
    Exits: Array<Outcome>
  }
};

interface Room {
  (name: string): {
    Movements: Array<Movement>
  }
};

interface Rooms {
  (name: Room)
};

interface Definitions {
  Rooms: Rooms
};

const defs: Definitions = {
  Rooms: {
    "Kitchen": {
      Movements: [
        "Living Room": {
          Points: 3,
          Exits: [
            {Difference: "<= 1", Room: "Bedroom"},
            {Difference: "2", Room: "Living Room"},
          ]
        },
        Bedroom: {
          Points: 2,
          Exits: [
            {Difference: "<= 2", Room: "Closet"},
          ]
        },
      ]
    }
  }
}

I'm getting the following error, but not understanding the issue:

[ts]
Type '{ Rooms: { "Kitchen": { Movements: any[]; }; }; }' is not assignable to type 'Definitions'.
  Types of property 'Rooms' are incompatible.
    Type '{ "Kitchen": { Movements: any[]; }; }' is not assignable to type 'Rooms'.
      Object literal may only specify known properties, and '"Kitchen"' does not exist in type 'Rooms'.
(property) "Kitchen": {
    Movements: any[];
}

Any ideas?

Upvotes: 1

Views: 171

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 250056

There are several problems with your code, (name: string) defines a call signature, you probably want an index signature : [name: string], meaning the object can be accessed using [] with any string.

Also your object literal suggests that the Room interface is not indexable by a string but rather just has a Movements field.

This works, and should get you started:

interface Outcome {
    Difference: string,
    Room: string
};

interface Movement {
    [name: string]: {
        Points: number,
        Exits: Array<Outcome>
    }
};

interface Room {
    Movements: Array<Movement>
};

interface Rooms {
    [name: string]: Room
};

interface Definitions {
    Rooms: Rooms
};

const defs: Definitions = {
    Rooms: {
        "Kitchen": {
            Movements: [{
                "Living Room": {
                    Points: 3,
                    Exits: [
                        { Difference: "<= 1", Room: "Bedroom" },
                        { Difference: "2", Room: "Living Room" },
                    ]
                },
                Bedroom: {
                    Points: 2,
                    Exits: [
                        { Difference: "<= 2", Room: "Closet" },
                    ]
                },
            }]
        }
    }
}

Playground link

Upvotes: 1

Related Questions