我是React和Redux的新手,并且正在使用Typescript进行一个小项目。我创建了第一个reducer和action,但是有一个问题:每当尝试访问有效内容时,都会得到一个Type error: property X does not exist in type
。
动作:
import { Action } from 'redux';
export const LOGIN_ACTION = 'login';
export const LOGIN_SUCCESS_ACTION = 'login-sucesss';
export const LOGIN_FAILED_ACTION = 'login-failed';
export interface LoginAction extends Action {
type: string;
payload: {
username: string;
password: string;
};
}
export function login(username: string, password: string): LoginAction {
return {
type: LOGIN_ACTION,
payload: { username, password },
};
}
export interface LoginSuccessAction extends Action {
type: string;
payload: {
loginToken: string;
};
}
export function loginSuccess(loginToken: string): LoginSuccessAction {
return {
type: LOGIN_SUCCESS_ACTION,
payload: { loginToken },
};
}
export interface LoginFailedAction extends Action {
type: string;
payload: {
error: Error;
};
}
export function loginFailed(error: Error): LoginFailedAction {
return {
type: LOGIN_FAILED_ACTION,
payload: { error },
};
}
export type LoginActions = LoginAction | LoginSuccessAction | LoginFailedAction;
减速器:
import { LOGIN_ACTION, LOGIN_FAILED_ACTION, LOGIN_SUCCESS_ACTION, LoginActions } from '../../actions/login.action';
import {
REQ_STATUS_FAIL,
REQ_STATUS_PROCESSING,
REQ_STATUS_SUCCESS,
REQ_STATUS_UNDEFINED,
} from '../../common/request-status';
export interface LoginState {
username: string;
password: string;
loginToken: string;
loginError?: Error;
status?: number;
}
export const initialState: LoginState = {
username: '',
password: '',
loginToken: '',
loginError: undefined,
status: REQ_STATUS_UNDEFINED,
};
export function loginReducer(state: LoginState = initialState, action: LoginActions): LoginState {
switch (action.type) {
case LOGIN_ACTION:
console.log('I was here', action.payload);
return { ...state, username: action.payload.username, password: action.payload.password, status: REQ_STATUS_PROCESSING };
case LOGIN_SUCCESS_ACTION:
return { ...state, loginToken: action.payload.loginToken, status: REQ_STATUS_SUCCESS };
case LOGIN_FAILED_ACTION:
return { ...state, loginToken: '', loginError: action.payload.error, status: REQ_STATUS_FAIL };
default:
return state;
}
}
问题是在访问有效内容的属性时出现很多类型错误,例如:action.payload.username
或action.payload.password
。
Property 'username' does not exist on type '{ username: string; password: string; } | { loginToken: string; } | { error: Error; }'.
Property 'username' does not exist on type '{ loginToken: string; }'
Property 'password' does not exist on type '{ username: string; password: string; } | { loginToken: string; } | { error: Error; }'.
Property 'password' does not exist on type '{ loginToken: string; }'.
你可以帮帮我吗?
您正在尝试在打字稿中使用区分的联合。区分联合使用switch
语句来根据给定的属性(type
在您的情况下)缩小每个分支的类型。区分联合的要求是,type
属性必须为文字类型(在您的情况下为字符串文字类型)。由于您为操作的类型定义了常量,因此可以typeof constant
用来获取为常量推断的字符串文字类型。
interface Action { } // Dummy for self contained sample
export const LOGIN_ACTION = 'login';
export const LOGIN_SUCCESS_ACTION = 'login-sucesss';
export const LOGIN_FAILED_ACTION = 'login-failed';
export interface LoginAction extends Action {
type: typeof LOGIN_ACTION; // !! here we assign the string literal type of the constant
payload: {
username: string;
password: string;
};
}
export function login(username: string, password: string): LoginAction {
return {
type: LOGIN_ACTION,
payload: { username, password },
};
}
export interface LoginSuccessAction extends Action {
type: typeof LOGIN_SUCCESS_ACTION; // !! here we assign the string literal type of the constant
payload: {
loginToken: string;
};
}
export function loginSuccess(loginToken: string): LoginSuccessAction {
return {
type: LOGIN_SUCCESS_ACTION,
payload: { loginToken },
};
}
export interface LoginFailedAction extends Action {
type: typeof LOGIN_FAILED_ACTION; // !! here we assign the string literal type of the constant
payload: {
error: Error;
};
}
export function loginFailed(error: Error): LoginFailedAction {
return {
type: LOGIN_FAILED_ACTION,
payload: { error },
};
}
export type LoginActions = LoginAction | LoginSuccessAction | LoginFailedAction;
export interface LoginState {
username: string;
password: string;
loginToken: string;
loginError?: Error;
status?: number;
}
export const initialState: LoginState = {
username: '',
password: '',
loginToken: '',
loginError: undefined,
status: 0,
};
export function loginReducer(state: LoginState = initialState, action: LoginActions): LoginState {
// Type guard fro discriminated union.
switch (action.type) {
case LOGIN_ACTION:
console.log('I was here', action.payload);
// action is LoginAction here
return { ...state, username: action.payload.username, password: action.payload.password, status: 0};
case LOGIN_SUCCESS_ACTION:
// action is LoginSuccessAction here
return { ...state, loginToken: action.payload.loginToken, status: 1 };
case LOGIN_FAILED_ACTION:
// action is LoginFailedAction here
return { ...state, loginToken: '', loginError: action.payload.error, status: -1 };
default:
return state;
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句