Home > front end >  Tree of locations object type declaration
Tree of locations object type declaration

Time:02-24

I have an object that represents a tree of locations. Each location may have sublocations(or not) and has a numeric id

{
    id: 0,
    USA: {
        id: 1,
        ARIZONA: {
            id: 2,
            PHOENIX: {
                id: 3
            },
            TUSCANY: {
                id: 4
            }
        },
        ALABAMA: {
            id: 4,

        }
    },
    CANADA: {
        id: 6,
        ONTARIO: {
            id: 7,
            TORONTO: {
                id: 8
            },
            OTTAWA: {
                id: 9
            }
        },
        QUEBEC: {
            id: 10,
            MONTREAL: {
                id: 11
            }
        },
    }
    UK: {
        id: 12,
        LONDON: {
            id: 13
        }
    }
}

I am trying to represent this as an interface

interface Location  {
    id: number;
    [key in string]?:  Location

}

but it doesn't let me saying:

A mapped type may not declare properties or methods.ts(7061) I also tried

interface Location  {
    id: number;
    [key:string]:  Location

}

but it says

Property id of type number is not assignable to string index type Location

CodePudding user response:

You can use type instead of interface for this. We'll use it because then we can use intersections and unions. This we will use like the following:

type Foo = { id: number } | { id: number } & { [key: string]: Foo };

Foo can simply be an object with an id, or it can be an object with an id, plus a string index signature with more Foo objects.

If you want access to result in Foo | undefined, you can either use the noUncheckedIndexAccess compiler option (although rather strict), or just replace Foo in the index signature with something like Foo | undefined.

Playground

CodePudding user response:

type Idable = { id: number }

type IndexableLocation = { [key: string]: SomeLocation }

type SomeLocation = Idable | (Idable & IndexableLocation)


Illustration

const locations: SomeLocation = {
  id: 0,
  USA: {
    id: 1,
    ARIZONA: {
      id: 2,
      PHOENIX: {
        id: 3
      },
      TUSCANY: {
        id: 4
      }
    },
    ALABAMA: {
      id: 4,

    }
  },
  CANADA: {
    id: 6,
    ONTARIO: {
      id: 7,
      TORONTO: {
        id: 8
      },
      OTTAWA: {
        id: 9
      }
    },
    QUEBEC: {
      id: 10,
      MONTREAL: {
        id: 11
      }
    },
  },
  UK: {
    id: 12,
    LONDON: {
      id: 13
    }
  }
};

console.log((locations as IndexableLocation)["USA"]); // Type Asserion is important ere to satisfy the compiler

console.log(locations.id);
  • Related