Home > Back-end >  Infer string literal type from a JSON file
Infer string literal type from a JSON file

Time:10-14

I am reading from a large JSON file.
TypeScript is smart enough to infer the types of all the properties except one.

A simplified example:

type Animal = 'bear' | 'cat' | 'dog';

const data = {
  name: 'Max',
  age: 3,
  animal: 'dog',
  // 100s other properties from JSON file...
};

let theName: string = data.name; // perfect
let theAge: number = data.age; // perfect
let theAnimal: Animal = data.animal; // Error: Type 'string' is not assignable to type 'Animal'

(link to playground)

data.animal is used in several places, so I'm trying to avoid using as Animal everywhere.

What is the best way to fix this issue?
Is there any simple way I can tell the code that data.animal is an Animal?

CodePudding user response:

What about do like this?

type Animal = 'bear' | 'cat' | 'dog';

type Data = {
  name: string;
  age: number;
  animal: Animal;
}
const data: Data = {
  name: 'Max',
  age: 3,
  animal: 'dog',
  // 100s other properties from JSON file...
};

let theName: string = data.name; // perfect
let theAge: number = data.age; // perfect
let theAnimal: Animal = data.animal;

CodePudding user response:

You can use sum types and merge 2 definitions - the original definition of your data and the animal:Animal definitions.

type Animal = 'bear' | 'cat' | 'dog';

// the keys your want to exert
type DataWithAnimal = { [P in 'animal']: Animal } ;

const data = {
  name: 'Max',
  age: 3,
  animal: 'dog',
  // 100s other properties from JSON file...
};

// original data type
type DataType = typeof data;

// merge the 2 type definitions
type Data = DataType & DataWithAnimal;

// cast old type to new type
const typeData: Data = data as Data;

let theName: string = typeData.name; // perfect
let theAge: number = typeData.age; // perfect
let theAnimal: Animal = typeData.animal; // also perfect

  • Related