Как сделать Typesafe JSON с полями типа Enum? - PullRequest
5 голосов
/ 19 февраля 2020

У меня есть JSON файлы, которые соответствуют определенным мной интерфейсам TypeScript.

По большей части, при импорте таких JSON файлов и назначении их типизированным переменным, TypeScript способен вывести подпись типа автоматически (см. behaves exactly as I want в коде ниже). Однако, когда тип включает строковые перечисления , он больше не работает (см. DOES NOT behave).

Ниже приведен рабочий Минимальный воспроизводимый пример :

действительный. json

{ "id": 3.14159 }

неверно. 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'.

Я могу исправить ошибку go с помощью type IJsonTypeWithEnum = {"color": string}, но это не соответствует цели.

Есть ли обходной путь или переключатель компилятора, чтобы TypeScript распознавал значения перечисления внутри JSON как строки? Или это тупиковое ограничение TypeScript для вывода типа JSON?

Ответы [ 2 ]

1 голос
/ 06 мая 2020

Попробуйте использовать утверждение типа

const data: IJsonType = jsonData as IJsonType;
0 голосов
/ 06 мая 2020

Typescript не будет использовать его для вас в этом случае. Вам нужно будет его самостоятельно набрать

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

type IJsonType = {"color" : ColorType}


let validJson = {
   "color": "red" as ColorType
  // or
  // "color": "red" as const
}


let invalidJson = {
   "color": "chartreuse"
}


const data1: IJsonType = validJson;  // this MUST NOT error

const data2: IJsonType = invalidJson;  

data1 now valid

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...