简体   繁体   中英

Infer string literal type from a JSON file

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 ?

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

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM