打字稿在两个函数中重载了可选参数

时间:2021-02-03 16:21:30

标签: typescript typescript-generics

我有一个解析器函数,它可能有一个可选的第二个参数,称为 otherParams。我希望 Typescript 检查从 createResourceThunk 返回的函数是否也使用参数 otherParams 调用(如果它是在解析器函数中定义的)。 我怎样才能做到这一点? 最小可重现示例 here

export function createResourceThunk<T, Params, A, OtherParams extends A | never>(
  actions: ResourceActions<T>,
  resolver: (params: Params, otherParams: OtherParams) => Promise<T>
) {
  return function(params: Params, callbacks: Callbacks<T>, otherParams: OtherParams) {
    return async (dispatch: Dispatch) => {
      dispatch(actions.startAction());
      try {
        const data = await (otherParams ? resolver(params, otherParams) : resolver(params));
        ...
      } catch (error) {
        ...
      }
    };
  };
}

目前在返回函数的调用中总是期望第三个参数

1 个答案:

答案 0 :(得分:1)

鉴于您链接示例中的代码,我倾向于使用以下类型:

export function createResourceThunk<T, P, O extends [] | [otherParams: any]>(
  actions: ResourceActions<T>,
  resolver: (params: P, ...args: O) => Promise<T>
) {

  return function (params: P, callbacks: Callbacks<T>, ...otherParamsArr: O) {
    const [otherParams] = otherParamsArr; // if you care
    return async (dispatch: Dispatch) => {
      dispatch(actions.startAction());
      try {
        const data = await resolver(params, ...otherParamsArr);
        dispatch(actions.successAction({ data }));
        callbacks && callbacks.onSuccess && callbacks.onSuccess({ data });
      } catch (error) {
        dispatch(actions.errorAction({ error }));
        callbacks && callbacks.onError && callbacks.onError({ error });
      }
    };
  }
}

这里的重要部分是“可选”的第二个参数表示为剩余参数,其类型是 rest tuple 类型的 union。类型参数 Oparams 参数之后的参数列表。它被限制为具有零个元素 ([]) 或一个元素 ([otherParams: any])。因此,在您想说 otherParams 之前的任何地方,您都可以使用像 ...otherParamsArr 这样的休息参数。

这在实现内部工作,不需要错误或类型断言。您可以验证这是否也适用于调用方:

// with OptionalParam
const func1 = createResourceThunk('any', (a: { a: number }, b: string) => Promise.resolve('any'))
func1({ a: 1 }, { successAction: () => { } }, 'somestring') // okay
func1({ a: 1 }, { successAction: () => { } }); // error

// without OptionalParam
const func2 = createResourceThunk('any', (a: { a: number }) => Promise.resolve('any'))
func2({ a: 1 }, { successAction: () => { } }) // okay
func2({ a: 1 }, { successAction: () => { } }, 'somestring') // error

Playground link to code