0

下面我有getEntityId并且我想创建一个包装函数,它可以在许多函数getOrFail中使用,这些函数接受一个函数并返回一个调用传入函数的函数,并在返回或抛出之前断言它是真的。

import * as _ from 'lodash'

export const getEntityId = (value: any, entity: string): number | null => {
  if (typeof value === 'number') return value
  if (_.get(value, 'id')) return value.id
  if (_.get(value, `${entity}Id`)) return value.id
  return null
}

export const getOrFail = <A, T> (fn: (...a: T[]) => A, message) => (...args: T[]) => {
  const value = fn(...args)
  if (value) return value
  throw new Error(message);
}

export const getEntityIdOrFail = getOrFail(getEntityId, 'failed getting entity id')

我也试过这个:

export const getOrFail = (fn, message) => (...args: ArgumentTypes<typeof fn>): ReturnType<typeof fn> => {
  const value = fn(...args)
  if (value) return value
  throw new Error(message);
}

我正在寻找一种使用泛型来制作它的方法,以便getEntityIdOrFail具有正确的类型信息。这怎么可能?

所以我需要明白三件事:

  1. 如何将fn类型参数传递给(...args)
  2. 如何传递fn返回类型
  3. 如何null从返回值中删除
4

1 回答 1

0

您可以使用具有不同数量参数的版本重载该函数:

function getOrFail<A1, R>(fn: (a1: A1) => R, message: string): (a1: A1) => Exclude<R, null>;
function getOrFail<A1, A2, R>(fn: (a1: A1, a2: A2) => R, message: string): (a1: A1, a2: A2) => Exclude<R, null>;
function getOrFail<A1, A2, A3, R>(fn: (a1: A1, a2: A2, a3: A3) => R, message: string): (a1: A1, a2: A2, a3: A3) => Exclude<R, null>;
function getOrFail(fn: any, message: string) {
    return ((...args: any[]) => {
  const value = fn(...args)
  if (value) return value
  throw new Error(message);
});
}

// getEntityIdOrFail is of type (a1: any, a2: string) => number
export const getEntityIdOrFail = getOrFail(getEntityId, 'failed getting entity id')
于 2019-09-04T20:10:17.757 回答