Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do Typesafe JSON with fields of Enum type?

I have some JSON files that conform to TypeScript interfaces that I have defined.

For the most part, when importing such JSON files and assigning them to typed variables, TypeScript is able to infer the type signature automatically (see behaves exactly as I want in the code below). However when the type includes string enums, it no longer works (see DOES NOT behave).

The following is a working Minimal, Reproducible Example:

valid.json

{ "id": 3.14159 }

invalid.json

{ "id": "3.14159" }

validEnum.json

{ "color": "red" }

invalidEnum.json

{ "color": "chartreuse" }

index.ts

import validJson from './valid.json'
import invalidJson from './invalid.json'
import validJsonEnum from './validEnum.json'
import invalidJsonEnum from './invalidEnum.json'

type ColorType = 'red' | 'blue' | 'yellow'

type IJsonType = {"id": number}
type IJsonTypeWithEnum = {"color": ColorType}

// behaves exactly as I want
const a: IJsonType = validJson    // no error
const b: IJsonType = invalidJson  // ERROR: Type 'string' is not assignable to type 'number'.

// DOES NOT behave as I want: SHOULD NOT error
const c: IJsonTypeWithEnum = validJsonEnum    // ERROR: Type 'string' is not assignable to type 'ColorType'.

// DOES NOT behave as I want: error should be that "chartreuse" is not assignable to type 'ColorType'
const d: IJsonTypeWithEnum = invalidJsonEnum  // ERROR: Type 'string' is not assignable to type 'ColorType'.

I can make the error go away with type IJsonTypeWithEnum = {"color": string}, but that defeats the purpose.

Is there any work-around or a compiler switch to make TypeScript recognize enum values inside JSON as strings? Or is it a dead-end TypeScript limitation for JSON type inference?

like image 838
vitaly-t Avatar asked Feb 19 '20 03:02

vitaly-t


People also ask

How are enums represented in JSON?

JSON has no enum type. The two ways of modeling an enum would be: An array, as you have currently. The array values are the elements, and the element identifiers would be represented by the array indexes of the values.

Can I use enum as type in TypeScript?

You can do this because enums are compiled to JavaScript objects, so they also have a value representation in addition to being types. direction can therefore only be set to a member of the CardinalDirection enum.

What is enum TS?

Enums stands for Enumerations. Enums are a new data type supported in TypeScript. It is used to define the set of named constants, i.e., a collection of related values. TypeScript supports both numeric and string-based enums. We can define the enums by using the enum keyword.

Should enums be capitalized TypeScript?

Use uppercase letters for your enums - they are global constants which have usable values. They are more than just types, which use usually like Foo or TFoo . The keys on an enum tend to be titlecase.


1 Answers

Try to use type assertion

const data: IJsonType = jsonData as IJsonType;
like image 138
Damian Plewa Avatar answered Oct 29 '22 13:10

Damian Plewa