При написании кода redux я наткнулся на поведение типа, которого я не понимаю.
В приведенном ниже коде вы не можете назначить anyaction на iaction. Но почему-то назначение anyaction на iaction2 нормально. Я пытаюсь применить здесь часть спецификации «Совместимость назначений», но не могу объяснить эту разницу.
Что происходит? Очевидно, существуют значения типа AnyAction, которые нельзя присвоить IAction2.
export interface ILoadUserBegin {
type: "LOAD_USER_BEGIN";
}
export interface ILoadUserSuccess {
type: "LOAD_USER_SUCCESS";
response: number;
}
type IAction = ILoadUserSuccess;
type IAction2 = ILoadUserBegin | ILoadUserSuccess;
// these are redux types
interface Action {
type: any;
}
interface AnyAction extends Action {
[extraProps: string]: any;
}
// tests
let iaction: IAction = { type: "LOAD_USER_SUCCESS", response: 2 };
let iaction2: IAction2 = { type: "LOAD_USER_BEGIN" };
let anyaction: AnyAction = { type: "foo" };
// ERROR
// Type 'AnyAction' is not assignable to type 'ILoadUserSuccess'.
// Property 'response' is missing in type 'AnyAction'.
iaction = anyaction;
// But this is OK!
iaction2 = anyaction;






Прежде всего, Action можно отнести к ILoadUserBegin.
let iaction1: ILoadUserBegin = anyaction; // ok
Поэтому неудивительно, что его можно присвоить типу объединения, который содержит ILoadUserBegin в качестве одного из его членов.
Следующий вопрос: почему переменная типа Action может быть присвоена ILoadUserBegin?
Поскольку Action имеет свойство type, объявлено, что оно имеет тип any.
any - это особый тип, который совместим со всем, он подавляет проверку типов, поэтому тип {type: any} совместим с типом {type: "LOAD_USER_BEGIN"}.
Спасибо,
type: anyдействительно виноват. Если я заменю его наtype: string, то все пойдет как положено.