typescript - 属性在联合类型上不存在
我有一个关于联合类型的问题:
起初,我定义了两个接口:
export interface Action {
type: string;
export interface ActionWithPayload<T> extends Action {
payload: T;
}
接下来,我定义几个类型和一个用于后续使用的联合类型:
export type LoadDrafts = Action;
export type LoadDraftsSuccess = ActionWithPayload<{ [K: string]: Draft }>;
export type DraftsActionsUnion =
| LoadDrafts
| LoadDraftsSuccess;
最后,我在我的 reducer 函数中使用联合类型:
export const draftsReducer = (
state = initialState,
action: DraftsActionsUnion
): DraftsState => {
switch (action.type) {
case DraftsActionsTypes.LoadDrafts: {
return {
...state,
loading: true
};
}
case DraftsActionsTypes.LoadDraftsSuccess: {
return {
...state,
loading: false,
loaded: true,
entities: {
...state.entities,
...action.payload
}
};
}
default: {
return state;
}
}
};
问题就在这里——编译器抱怨我的联合类型上不存在属性 payload(...action.payload 导致了这个问题):
[ts]
Property 'payload' does not exist on type 'DraftsActionsUnion'.
Property 'payload' does not exist on type 'Action'.
不知道这是一个错误还是我做错了什么。
答案#1
我认为你的两个动作类型中的类型判别字段缺少字符串字面值。你需要这个来在 switch 中区分实际在 case 块中的类型。有不止一种方法可以做到这一点,但这里有一种你可以使用的方法。
export interface Action<K extends string> {
type: K;
}
export interface ActionWithPayload<K, T> extends Action<K> {
payload: T;
}
export type LoadDrafts = Action<‘loadDrafts’>;
export type LoadDraftsSuccess = ActionWithPayload<‘loadDraftSuccess’, { [K: string]: Draft }>;
这使得你的类型列成为一个通用字符串字面量,可以在继承你的接口时指定。
重要的是你的类型值应为字符串字面量,而不是字符串,这样你会得到有限的一组值,而不是实际上无限的字符串可能性。
