typescript - 键入自定义操作类型
问题描述
我正在遵循本次演讲中的设计模式(您无需观看即可理解我的问题): https ://www.youtube.com/watch?v=5gl3cCB_26M
主要概念是为 redux 的类型提供标识符。例如,一个 api 请求的动作创建者应该有这样的类型:[Books] API_REQUEST
。动作创建者基本上是在组合[Books]
然后API_REQUEST
将其作为自己动作的一种类型。[Books]
被赋予动作创建者的思想论据。它允许同时为多个功能执行多个 api 请求,并且不会在(例如)中间件中混淆它们。
所以这在纯 Javascript 中很简单。但是使用 Typescript,我们需要为中间件和 reducer 键入我们的操作。键入 redux 操作的主要思想是执行一个type: typeof API_REQUEST
操作,以便 Typescript 可以通过其类型识别该操作(根据文档的这一部分:https ://redux.js.org/recipes/usage-with-typescript )。
现在的问题是:如何API_REQUEST
使用 Typescript 无法识别的 redux 类型键入操作(在本例中为 for )?
这是一个具体的例子,所以你会有更好的理解:
// types/api.ts
export const API_REQUEST = 'API_REQUEST';
export const API_SUCCESS = 'API_SUCCESS';
interface ApiRequestAction {
type: string; // can't be `typeof API_REQUEST` because the final action will be `[Books] API_REQUEST`
payload: {
body: object | null;
};
meta: {
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
url: string;
feature: string;
};
}
interface ApiSuccessAction {
type: string; // same as before
payload: {
data: object[];
};
meta: {
feature: string;
};
}
export type ApiActions = ApiRequestAction | ApiSuccessAction;
// actions/api.ts
import { API_REQUEST, API_SUCCESS, ApiActions } from '../types/api';
export const apiRequest = ({ feature, body, method, url }): ApiActions => ({
type: `${feature} ${API_REQUEST}`, // [Books] API_REQUEST
payload: {
body
},
meta: {,
method,
url,
feature
}
});
export const apiSuccess = ({ feature, data }): ApiActions => ({
type: `${feature} ${API_SUCCESS}`, // [Books] API_SUCCESS
payload: {
data
},
meta: {
feature
}
});
// reducer/books.ts
import { API_REQUEST, ApiActions } from '../types/api';
export const booksReducer = (state = [], action: ApiActions) => {
if (action.type === `[Books] ${API_REQUEST}`) {
// Here's the issue, Typescript can't be like "Alright, in this block action should be the same as decribed in ApiRequestAction because of the condition. So he'll have access to `action.payload.method` and all the others..."
// But nop, he's just giving an error because he can't know if the action is the same a ApiRequestAction or ApiSuccessAction.
// This is because I can't use `typeof` in ApiRequestAction because the type of the action can't be known before the action is created.
// Then Typescript is throwing an error because he can't know what the action is. And so he can't know if `action.method.url` can be accessed because is only in one of the two possible actions.
console.log(action.meta.url); // Property 'url' does not exist on type '{ feature: string; }'
// Do some stuff with `action`
}
}
那么有没有办法解决这个问题?我考虑过某种正则表达式类型而不是普通的string
(例如:),type: /\[\w+\] API_REQUEST/
但我认为这是不可能的。
我希望这是可以理解的,这很难解释。如果您有任何问题,请随时问我。
解决方案
您可以使用以下函数强制转换接口:
export function isBooksRequest(action:any): action is ApiRequestAction {
return action.type === `[Books] ${API_REQUEST}`;
}
if (isBooksRequest(action)) {
// action is considered as ApiRequestAction
console.log(action.meta.url);
}
关键字is
,是:在此处typeof type guards
查看文档
推荐阅读
- iframe - Google Drive Iframe 无法在 Safari 浏览器中播放视频
- javascript - 试图从另一个变量值引用一个变量
- powershell - 隐藏通信站点上一组用户的齿轮图标
- laravel - Laravel 作为数组加入 json 响应
- plsql - validate_conversion 不在包中编译,而是作为独立过程编译
- flutter - 在 Flutter 网站上展示广告(flutter web app)
- wpf - MvvmCross:在另一个视图中查看(或等效于 CaliburnMicro Conductor)
- python-3.x - 我收到错误:“列表分配超出范围”
- angular - 用户第一次单击时,角度材料未设置正确的数据值
- amazon-web-services - 从 aws ec2 连接到远程网络