Эта проблема связана с тем, как проверки избыточных свойств работают в профсоюзах.Если литерал объекта назначен переменной типа объединения, свойство не будет помечено как избыточное, если оно присутствует в любом членов объединения.Если мы не считаем избыточные свойства ошибкой (и, за исключением литералов объекта, они не считаются ошибкой), указанным литералом объекта может быть экземпляр LoadingState
(экземпляр с isLoading
, установленным на true
как указано и несколько лишних свойств).
Чтобы обойти это нежелательное поведение, мы можем добавить свойства к LoadingState
, чтобы сделать ваш объект буквально несовместимым с LoadingState
type LoadingState = { isLoading: true; isSuccess?: never }
type SuccessState = { isLoading: false; isSuccess: true; }
type ErrorState = { isLoading: false; isSuccess: false; errorMessage: string; }
type State = LoadingState | SuccessState | ErrorState;
const testState: State = { // error
isLoading: true,
isSuccess: true,
errorMessage: "Error!"
}
Мы могли бы даже создать тип, который бы гарантировал добавление такого члена
type LoadingState = { isLoading: true; }
type SuccessState = { isLoading: false; isSuccess: true; }
type ErrorState = { isLoading: false; isSuccess: false; errorMessage: string; }
type UnionKeys<T> = T extends any ? keyof T : never;
type StrictUnionHelper<T, TAll> = T extends any ? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, never>> : never;
type StrictUnion<T> = StrictUnionHelper<T, T>
type State = StrictUnion< LoadingState | SuccessState | ErrorState>
const testState: State = { // error
isLoading: true,
isSuccess: true,
errorMessage: "Error!"
}