我正在尝试使用 typescript/redux 创建一个 reducer ,但遇到了这个错误
Property 'loginToken' does not exist on type '{ loginToken: string; } | { error: Error; } | { username: string; password: string; }'.
Property 'loginToken' does not exist on type '{ error: Error; }'
我的 reducer 如下:
export default (state = userState, action: UsersActions) => {
switch (action.type) {
case ActionTypes.USER_LOGIN_REQUEST:
return {
...state,
isAuthenticated: false,
isLoading: true,
};
case ActionTypes.USER_LOGIN_SUCCESS:
return {
...state,
isAuthenticated: true,
loginToken: action.payload.loginToken,
isLoading: false,
};
我的操作类型:
export interface UserLoginRequest extends Action {
type: typeof ActionTypes.USER_LOGIN_REQUEST; // !! here we assign the string literal type of the constant
payload: {
username: string;
password: string;
};
}
export interface UserLoginSuccess extends Action {
type: typeof ActionTypes.USER_LOGIN_SUCCESS; // !! here we assign the string literal type of the constant
payload: {
loginToken: string;
};
}
export interface UserLoginFailure extends Action {
type: typeof ActionTypes.USER_LOGIN_FAILURE; // !! here we assign the string literal type of the constant
payload: {
error: Error;
};
}
export interface User {
username: string;
password: string;
loginToken: string;
loginError?: Error;
status?: number;
}
export type UsersActions =
| UserLoginSuccess
| UserLoginFailure
| UserLoginRequest;
Action 类型是一个像这样的枚举:
enum ActionTypes {
USER_LOGIN_REQUEST = 'request',
USER_LOGIN_SUCCESS = 'success',
USER_LOGIN_FAILURE = 'failure',
};
也许我没有得到有关 Typescript 的信息,这就是为什么?如果可以提供任何资源或见解,我们将不胜感激。
最佳答案
问题是 UsersActions
可以是以下三者之一 - UserLoginSuccess、UserLoginFailure 或 UserLoginRequest - 它是联合类型。
在“成功”的情况下,您知道登录 token 将存在,并且类型是 UserLoginSuccess - 但 TypeScript 没有任何方式知道这一点,所以它告诉您您可能正在尝试从(例如)UserLoginFailure
类型获取 loginToken
属性。
解决方案是you've got to narrow the type when you want to work with it 。由于联合类型上没有可以打开的通用属性,因此我认为执行此操作的唯一方法是将有效负载转换为正确的类型:
case ActionTypes.USER_LOGIN_SUCCESS:
return {
...state,
isAuthenticated: true,
loginToken: (action.payload as UserLoginSuccess).loginToken,
isLoading: false,
};
编辑
抱歉,我刚刚重新阅读了您的问题,发现有一个更好的解决方案 - 当您创建联合类型时,您使用 typeof
作为操作类型 -
export interface UserLoginRequest extends Action {
type: typeof ActionTypes.USER_LOGIN_REQUEST;
// ...
}
所以 type
将是该属性的类型 - 但我猜你真正想要做的是使其成为已知值?
我不知道 ActionsTypes
的定义是什么,但如果这是一个 enum
-
enum ActionTypes {
USER_LOGIN_REQUEST = 'request',
USER_LOGIN_SUCCESS = 'success',
USER_LOGIN_FAILURE = 'failure',
};
然后您可以更改类型定义以使用枚举类型 -
interface UserLoginRequest extends Action {
type: ActionTypes.USER_LOGIN_REQUEST;
payload: {
username: string;
password: string;
};
}
现在,当您打开类型
时,TS 会正确地为您缩小有效负载 -
switch (action.type) {
case ActionTypes.USER_LOGIN_SUCCESS:
console.log(action.payload.loginToken); // TS is happy!
break;
default:
console.log('NOT A SUCCESS ACTION');
}
关于reactjs - 类型 'loginToken' 上不存在属性 '{ loginToken: string; } | { error: Error; } | { username: string; password: string; }',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67695950/