Typescript 我如何重构/抽象ngrx操作以减少打字错误?
更新: 似乎typescript fsa可能是我正在寻找的固执己见的库。关于实现细节的任何帮助都将非常棒 我觉得当我这样做的时候,我总是在复制和粘贴文件,然后只是重命名部分。我很容易犯典型的胖手指错误。虽然我目前没有测试我的项目,但如果一个项目需要100%的代码覆盖率,那么这可能是一项更加乏味的任务 称为计数器的简单操作示例:Typescript 我如何重构/抽象ngrx操作以减少打字错误?,typescript,redux,refactoring,action,ngrx,Typescript,Redux,Refactoring,Action,Ngrx,更新: 似乎typescript fsa可能是我正在寻找的固执己见的库。关于实现细节的任何帮助都将非常棒 我觉得当我这样做的时候,我总是在复制和粘贴文件,然后只是重命名部分。我很容易犯典型的胖手指错误。虽然我目前没有测试我的项目,但如果一个项目需要100%的代码覆盖率,那么这可能是一项更加乏味的任务 称为计数器的简单操作示例: import { Action } from '@ngrx/store'; export const INCREMENT = '[Counter] Increment
import { Action } from '@ngrx/store';
export const INCREMENT = '[Counter] Increment';
export const DECREMENT = '[Counter] Decrement';
export const RESET = '[Counter] Reset';
export class Increment implements Action {
readonly type = INCREMENT;
}
export class Decrement implements Action {
readonly type = DECREMENT;
}
export class Reset implements Action {
readonly type = RESET;
constructor(public payload: number) {}
}
export type All
= Increment
| Decrement
| Reset;
问题:
在typescript中,是否有任何模式可以通过简单的函数调用来获得上述一组类的功能?
例如:
TypeAction.create('Animal',['Add','Remove','Reset'])
注意:这是一个人为的函数签名,因为它没有考虑有效负载及其类型,只是举个例子
但该函数可以生成/表示/工作如下:
import { Action } from '@ngrx/store';
export const ADD = '[Animal] Add';
export const REMOVE = '[Animal] Remove';
export const RESET = '[Animal] Reset';
export class Add implements Action {
readonly type = ADD;
}
export class Remove implements Action {
readonly type = REMOVE;
}
export class Reset implements Action {
readonly type = RESET;
constructor() {}
}
export type All
= Add
| Remove
| Reset
最后,请不要思考,因为这不是一个好的解决方案。此外,“这是不可能的”也可能是一个可接受的答案…一点点升级建议
import { Action } from '@ngrx/store';
import { Animal } from 'animal.models';
export const ADD = '[Auth] Add';
export class Add implements Action {
readonly type = ADD;
constructor(public payload: Animal[]) {}
}
我想用crud异步操作来实现更好、更灵活的NGRX/redux/flux方式,这是我第一次感到害怕,我使用阿波罗团队用同步选项做的内部异步存储,我认为这是一个未来,很好地管理选项,有一个真正的来源,他们为crud*操作创建了通用的操作机制,当你想做一些特别的事情时,你可以使用DI并编写带有不可变函数的存储缩减器,或者我认为你可以使用effects(我从来没有尝试过)
为什么我认为这是一个未来?
apollo 2.0不需要重复CRUD操作的代码,每次在plus模式中捕获异步服务器操作的write effects都会通过对ts(生成器已准备好生产)的内省来保护您的类型,我对(James Baxley III编写的)和“未来功能”段落非常乐观-
当这个未来成为现在,服务器、浏览器、p2p live之间的一个存储和同步状态将是惊人的…另一个解决方案是使用像* 因此,您可以定义动作生成器,而不是“本机”NgRx动作类,例如 最后,在你的影响
@Effect() counterIncrement$ = this.actions$
.filter(counterIncrement.match)
.map(action => ...)
@Effect() counterDecrement$ = this.actions$
.filter(counterDecrement.match)
.map(action => ...)
@Effect() counterReset$ = this.actions$
.filter(counterReset.match)
.map(action => action.payload)
.map(payload => ...)
如您所见,除了初始定义之外,您从未使用易于键入的操作字符串,而是导入类型化操作生成器,这提供了额外的安全性,并且还支持在支持typescript的代码编辑器中进行函数替换
如果您的操作在集合之间是同质的,即每个集合都有相同的“添加”、“删除”、“重置”等操作(但有不同的“集合”前缀;并且不是每个集合都必须实现所有这些操作),那么您可以更进一步,创建通用操作生成器、通用还原生成器、,等等,这样您就不必重复相同的代码多次
编辑:根据Matthew的要求,这是一个更高级的示例,它包含了泛型和NgRX实体**
*我不是那个软件包的作者
**我是这个例子的作者。在这里粘贴完整的示例有点笨拙(并且超出了问题的重点),但是如果共享该链接不合适,请务必告诉我。ahh是的,这肯定会使键入更好。但仍然无法帮助解决它的冗长程度:(我没有使用它们,但是使用了新的entity软件包。它与fsa配合得好吗?如果可以,请您将其添加到问题中好吗?是的,它不知道在哪里添加它,但您可以更具体一些吗?顺便说一句,我发布了完整的代码,所以如果您需要完整的示例,请告诉我(不确定链接到这里是否合适)。实体包只是简化了样板文件。除此之外,我对它没有太多的了解。如果我的简单示例不能真正利用实体,那么我们就把它忽略掉。另外,如果你有活代码,只需更新问题..比如“这里有一个更可靠的回购协议可供学习。我认为ppl会很欣赏这一点。不仅是你,ngrx/store的正确实现是非常重复的,我在一个包上做了一些工作来减少这一点,但它增加了额外的复杂性。最好的办法是拥有多个action/reducer文件,并与一个整洁的索引文件相结合。
import { isType } from 'typescript-fsa';
export function counterReducer(state: CounterState = initialState, action: Action) {
if (isType(action, counterIncrement)) {
return { ...state, < your reduction here > };
}
if (isType(action, counterDecrement)) {
return { ...state, < your reduction here > };
}
if (isType(action, counterReset)) {
return { ...state, < your reduction here > };
}
return state;
};
store.dispatch(counterIncrement());
store.dispatch(counterDecrement());
store.dispatch(counterReset(42));
@Effect() counterIncrement$ = this.actions$
.filter(counterIncrement.match)
.map(action => ...)
@Effect() counterDecrement$ = this.actions$
.filter(counterDecrement.match)
.map(action => ...)
@Effect() counterReset$ = this.actions$
.filter(counterReset.match)
.map(action => action.payload)
.map(payload => ...)