泛型请求Effect类类型校验报错:返回Action无法被识别
泛型RequestEffect类中Action返回类型的TypeScript类型检查错误
问题描述
开发供其他类继承的泛型请求Effect类时,需传入三种Action类型实现泛型特性,但传递Action类型时触发TypeScript类型检查错误。代码可正常运行,但类型校验不通过,需明确为何返回的Action无法被正确识别。
代码示例
export interface ActionCreatorWithProps<TPropArgs extends object = {}> extends ActionCreator<string, (props: TPropArgs) => TPropArgs & TypedAction<string> > { } export interface EffectActions<S extends object, A extends object = {}, E extends object = {}> { startAction: ActionCreatorWithProps<A>; successAction: ActionCreatorWithProps<S>; errorAction: ActionCreatorWithProps<E>; } export abstract class RequestEffects<T extends object, A extends object = {}, E extends object = {}> { ///.... protected constructor( private requestEffectActions: RequestEffectActions<T, A>) { } makeRequestEffect$= createEffect(() => this.actions$.pipe( ofType<ActionCreatorWithProps<A>>(this.requestEffectActions.startAction), concatMap(() => this.executeRequest().pipe( map((response) => { return this.requestEffectActions.successAction(response); // * 直接返回action实例(比如return myAction())正常 // ** 断言为Action也不会报错 // return this.requestEffectActions.successAction(response) as Action; }), ), )) ); }
错误信息
TS2322: Type 'Observable<T & TypedAction<string>>' is not assignable to type 'Observable<T & TypedAction<string>> & (T & TypedAction<string> extends ActionCreator<string, Creator<any[], object>> ? "ActionCreator cannot be dispatched. Did you forget to call the action creator function?" : unknown)'. Type 'Observable<T & TypedAction<string>>' is not assignable to type 'T & TypedAction<string> extends ActionCreator<string, Creator<any[], object>> ? "ActionCreator cannot be dispatched. Did you forget to call the action creator function?" : unknown'. effect_creator.d.ts(12, 103): The expected type comes from the return type of this signature.
原因分析
错误源于createEffect的返回类型约束——它内置了一个条件类型,用于检查开发者是否误返回了ActionCreator函数而非Action实例。
由于类使用了泛型T,编译时TypeScript无法确定T & TypedAction<string>是否会意外匹配ActionCreator的类型签名。尽管实际调用successAction(response)返回的是Action实例,但泛型的不确定性让TypeScript触发了条件类型的错误分支,误判为可能返回了未调用的ActionCreator。
解决方案
方案1:显式约束泛型T不能是ActionCreator
在泛型参数中排除ActionCreator类型,让TypeScript明确T的范围:
// 定义类型,排除所有ActionCreator类型 type NotActionCreator = object & { [K in keyof ActionCreator<string, any>]?: never }; export abstract class RequestEffects<T extends NotActionCreator, A extends object = {}, E extends object = {}> { // ... 其余代码不变 }
此方式能让TypeScript确定T & TypedAction<string>不可能是ActionCreator,条件类型会直接走正确分支。
方案2:安全的类型断言
若不想修改泛型约束,可在返回时使用更精确的类型断言,替代宽泛的as Action:
map((response) => { return this.requestEffectActions.successAction(response) as ReturnType<typeof this.requestEffectActions.successAction>; }),
该断言基于实际的successAction返回类型,比直接断言为Action更安全。
方案3:调整EffectActions的泛型定义
明确指定successAction的返回类型为Action,避免依赖泛型推导:
export interface EffectActions<S extends object, A extends object = {}, E extends object = {}> { startAction: ActionCreatorWithProps<A>; successAction: (props: S) => S & TypedAction<string> & Action; // 显式混入Action接口 errorAction: ActionCreatorWithProps<E>; }
此方式能让TypeScript直接识别返回值为Action实例,消除条件类型的歧义。
内容的提问来源于stack exchange,提问作者Diego
相关产品推荐
相关产品推荐

