首页 > 解决方案 > Typescript:如何从包含泛型的类型中获取所有可能的返回值

问题描述

我需要从函数中导出所有可能的返回类型。例如,

interface Action<T, P> {
  type: T;
  payload: P;
}

export type Actions =
  | Action<typeof CHANGE_STATE, ChangeStateReturn["payload"]>
  | Action<typeof SET_PROGRESS_ERROR, SetProgressErrorReturn["payload"]>
  | Action<typeof SNACKBAR_OPEN, SnackbarOpenReturn["payload"]>;

export interface Reducer {
  (state: State, action: Actions): State;
}

const reducer: Reducer = (state, action) => {
  switch (action.type) {
    case CHANGE_STATE:
      return Object.assign<{}, State, State>({}, state, {
        ...state,
        [action.payload.stateName]: {
          ...state[action.payload.stateName],
          [action.payload.key]: action.payload.value
        }
      });

    default:
      return state;
  }
};
export default reducer;

这样做的原因是因为我需要导出Actions作为我的状态上下文的一部分:

interface CreateCtx {
  (): readonly [
    Context<{
      state: State;
      dispatch: Dispatch<Actions>;
    }>,
    Provider
  ];
}

interface Provider {
  (props: PropsWithChildren<{}>): JSX.Element;
}

export const createCtx: CreateCtx = () => {
  const defaultDispatch: Dispatch<Actions> = () => initialState;
  const ctx = createContext({
    state: initialState,
    dispatch: defaultDispatch
  });
  const Provider: Provider = props => {
    const [state, dispatch] = useReducer(reducer, initialState);
    return <ctx.Provider value={{ state, dispatch }} {...props} />;
  };
  return [ctx, Provider];
};

export const [Store, StateProvider] = createCtx();

这是该changeState()函数的一个示例:

export interface ChangeState<
  S extends keyof State = keyof State,
  K extends keyof State[S] = keyof State[S]
> {
  (stateName: S, key: K, value: State[S][K]): ChangeStateReturn<S, K>;
}

export interface ChangeStateReturn<
  S extends keyof State,
  K extends keyof State[S]
> {
  type: typeof CHANGE_STATE;
  payload: {
    stateName: S;
    key: K;
    value: State[S][K];
  };
}
export const changeState: ChangeState = (stateName, key, value) => {
  return {
    type: CHANGE_STATE,
    payload: {
      stateName,
      key,
      value
    }
  };
};

我对此有一个重大问题。首先,有效载荷值keyvalue总是等于never

其次,我需要以某种方式返回所有可能的返回值类型(from Actions)作为我的状态上下文的一部分,但是由于changeState()函数中使用了泛型,这意味着我以某种方式返回可能发生的每个可能的组合(例如,对于每个可能的组合S 和 K)。

我非常坚持这一点。有任何想法吗?

编辑: 这是一个演示的链接,应该更好地解释这一点

标签: typescript

解决方案


我设法解决了它...

所以问题是它Action<typeof CHANGE_STATE, ChangeStateReturn["payload"]>不能正常工作,因为它的默认值<S>是一个枚举(所有可能的keyof State值)。

为了解决这个问题,我需要为类型Action的每个可能值添加一个。<S><Actions>

例如,

export type Actions =
  | Action<typeof CHANGE_STATE, ChangeStateReturn<"formOne">["payload"]>
  | Action<typeof CHANGE_STATE, ChangeStateReturn<"formTwo">["payload"]>
  | Action<typeof CHANGE_STATE, ChangeStateReturn<"foo">["payload"]>
  | Action<typeof CHANGE_STATE, ChangeStateReturn<"bar">["payload"]>
  | Action<typeof SET_PROGRESS_ERROR, SetProgressErrorReturn["payload"]>
  | Action<typeof SNACKBAR_OPEN, SnackbarOpenReturn["payload"]>;

推荐阅读