打字稿装饰器类型推断问题

时间:2019-09-16 16:24:29

标签: typescript redux decorator typescript-typings

当我想输入其功能参数时,TS装饰器出现问题。 考虑它是在redux上下文中。装饰器@OnAction的{​​{1}}截获动作。

我希望从我给装饰器的类型中获得一个,该函数要求具有相应动作类型的函数。 基本上,对于type,我希望装饰器询问带有参数@OnAction('history/modal/toggle')的函数。

但是使用以下代码,我的装饰器上出现编译错误。

Playground

action: HistoryModalToggleAction
// Sample.ts

export interface HistoryModalReducerProps {
  visible: boolean;
  otherStuff: string;
}

export interface HistoryModalToggleAction extends Action<'history/modal/toggle'> {
  visible: boolean;
}

export type StoreAction = HistoryModalToggleAction | Action<'otherAction1'> | Action<'otherAction2'>;

export class Sample {

  @OnAction('history/modal/toggle')
  onToggle(state: Readonly<HistoryModalReducerProps>, action: HistoryModalToggleAction): Readonly<HistoryModalReducerProps> {

    if (!action.visible)
      return state;
    else
      return {
        ...state,
        visible: true
      };
  }

}

经过简化的编译错误表示,在我的函数中,// OnAction.ts type RestrictedMethod<A extends StoreAction> = ( prototype: any, key: string, descriptor: TypedPropertyDescriptor<( state: any, action: A ) => any> ) => void; export function OnAction<A extends StoreAction>(type: A['type']): RestrictedMethod<A> { const restrictedMethod: RestrictedMethod<A> = (prototype, key, descriptor) => { // ... }; return restrictedMethod; } 无法分配给HistoryModalToggleAction。因此,我的装饰器等待带有StoreAction而不是action: StoreAction的函数。甚至我对这种缺乏自卑的行为闭上了眼睛,这似乎是错误的,这些类型是兼容的。

我的打字稿版本是action: HistoryModalToggleAction

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

找到解决方案!

我必须更改OnAction签名的类型以缩小操作类型:

type NarrowAction<T, N> = T extends Action<N> ? T : never;

export function OnAction<T extends StoreAction['type']>(type: T): RestrictedMethod<NarrowAction<StoreAction, T>> {

  return (prototype, key, descriptor) => {

    // ...

  };
}

现在可以了! Playground