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?
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.
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.
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.
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.
Try to use type assertion
const data: IJsonType = jsonData as IJsonType;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With