键入函数调用的映射

时间:2018-03-26 18:39:38

标签: typescript typescript-typings

我在输入使用ACTIONS_MAP调用的函数时遇到了麻烦。我得到了一个"无法调用类型缺少呼号的表达式。"在ACTIONS_MAP[action.type](action);行。

我认为它发生的是fetchActionnavigateActionopenModalAction各自期望action参数及其各自的类型。因此,在编译TS时,我不能100%确定我将正确的类型传递给每个动作函数。

import { fetchAction, FetchAction } from './fetch';
import { navigateAction, NavigateAction } from './navigate';
import { openModalAction, OpenModalAction } from './openModal';

const ACTIONS_MAP = {
  $fetch: fetchAction,
  $navigate: navigateAction,
  $openModal: openModalAction,
};

export type Action =
  | FetchAction
  | NavigateAction
  | OpenModalAction;

export function dispatchActions(actions: Action[]) {
  actions.forEach(action => {
    ACTIONS_MAP[action.type](action);
  });
}

有没有办法输入这个或什么是这种方法的好选择?

编辑: 这是fetch.ts的一个人为设想的例子,其他的是相似的。

export interface FetchAction {
    type: '$fetch';
    // More types here
}


export function fetchAction(action: FetchAction) {
    // Do some work here
}

2 个答案:

答案 0 :(得分:2)

在这种情况下避免使用开关的唯一方法(至少我能想到)它使用类型断言。虽然不理想,但有时类型断言在Typescript代码中是必要的,尽管我们应该在绝对必要时使用它们:

type ActionHandler = (a: Action)=> void;
export function dispatchActions(actions: Action[]) {
    actions.forEach(action => {
        (ACTIONS_MAP[action.type] as ActionHandler)(action);
    });
}  

答案 1 :(得分:0)

如果您不需要传递对动作函数本身的引用,您可以尝试这样的实际解决方案:

type FooAction = {
  type: '$foo';
  payload: string;
}

type BlahAction = {
  type: '$blah';
  payload: number;
}

type Action = FooAction | BlahAction;

function fooAction(action: FooAction) {
  console.log(action.payload);
}

function blahAction(action: BlahAction) {
  console.log(action.payload + 1)
}

const dispatchAction = (action: Action) => {
  switch (action.type) {
    case '$foo':
      // TS knows action must be a FooAction
      return fooAction(action);
    case '$blah':
      // TS knows action must be a BlahAction
      return blahAction(action);
    default:
      return;
  }
}

function dispatchActions(actions: Action[]) {
  actions.forEach(action => {
    dispatchAction(action);
  });
}

dispatchActions([
  { type: "$foo", payload: 'bar' },
  { type: "$blah", payload: 1 }
])

这可以让你在所有正确的地方打字(我认为)。但是,一旦离开每个给定的case语句,就会丢失缩小信息的类型。因此,您不能只返回该函数,然后再调用它。