Home > database >  Mapping an imported JSON file's string property value to an enum with TypeScript
Mapping an imported JSON file's string property value to an enum with TypeScript

Time:08-07

Let's say I have the following JSON:

[
  { "type": "one", "tile": { "x": 0, "y": 0 }},
  { "type": "two", "tile": null }
]

and I import it into a TypeScript module:

import dataJson from "data.json";

If I write type T = typeof dataJson; then T is defined as:

type T = ({
  type: string;
  tile: {
    x: number;
    y: number;
  };
} | {
  type: string;
  tile: null;
})[]

However, what I really want is this:

enum Type {
  one,
  two
}

interface Entry {
  type: Type,
  tile: {
    x: number,
    y: number
  } | null
}

const data: Entry[] = dataJson;

Unfortunately, TypeScript complains about this:

Types of property 'type' are incompatible. Type 'string' is not assignable to type 'FeatureType'. ts(2322)

I know why this is happening, but I can't seem to find a way around it. Is there a way to somehow coerce the auto-generated typeof dataJson into Entry?

CodePudding user response:

You don't like as any, understood. How about as Entry[]?

type Entry = (typeof dataJson)[number] & { type: "one" | "two" }
const data = dataJson as Entry[]

// as oppose to
const data: Entry[] = dataJson
// which still gives you error

TS Playground

It seems to me you're not familiar with enum in TS, I also include some side note on the topic (optional reading material).

CodePudding user response:

It seems like, so far, the only way to do this is the following (thanks to @hackape and @pascalpuetz for getting me there):

import dataJson from "data.json";

enum Type {
  one = "one",
  two = "two"
}

interface Entry {
  type: Type,
  tile: {
    x: number,
    y: number
  } | null
}

// "as any" seems to be the only way to coerce `type: string` to `type: Type`
const data: Entry[] = dataJson as any;

I'm okay with as any in this case since JSON is fundamentally much more weakly typed than TypeScript anyway.

  • Related