如何根据提供给第一个函数的参数来推断参数?

阿萨夫·阿维夫(Asaf Aviv)

我试图创建将采取单一的实用功能,valueenum并将推断基于一个返回的函数的参数interfacetype相匹配的领域value

我正在努力映射value和查找与字段type匹配的界面value

enum ActionTypes {
  One = 'One',
  Two = 'Two',
  Three = 'Three'
}

interface Action1 {
  type: ActionTypes.One
}

interface Action2 {
  type: ActionTypes.Two
  meta: {
    fieldName: '2'
  }
}

interface Action3 {
  type: ActionTypes.Three
  payload: number[]
  meta: {
    fieldName: '3'
  }
}

type AllActions =
  | Action1
  | Action2
  | Action3

const createAction = <T>(type: T) => (
  payload?: //infer payload from AllActions.type === T,
  meta?: //infer meta from AllActions.type === T,
  ) => ({
  type,
  ...payload && { payload },
  ...meta && { meta }
})

const action1 = createAction(ActionTypes.One)
action1()

const action2 = createAction(ActionTypes.Two)
action2(undefined, {
  meta: {
    fieldName: '2'
  }
})

const action3 = createAction(ActionTypes.Three)
action3([1, 2, 3], {
  meta: {
    fieldName: '3'
  }
})

TS游乐场

提香·切尔尼科娃·德拉戈米尔

您可以键入该函数,但是我们需要考虑以下几点:

  1. T应该扩展AllActions['type']以便捕获传入的值的文字类型。

  2. 要提取与之关联的动作,type: T我们需要使用预定义的条件类型Extract<AllActions, { type: T }>

  3. 由于根据T内部函数可以具有可变数量的参数,因此我们将需要在其余参数使用元组,以便将可变数量的参数分布到结果函数中。

  4. 将rest参数中的元组与手动声明的元组一起使用将导致参数名称丢失,因此[P, M],我们将构建一个函数签名,将参数提取为元组,然后将该元组散布回去,而不是构建像元组并将其散布开来。到rest参数(function fn(...a: Parameters<(x: number) => void>) {}将有一个名为的数字参数x,而function fn(...a:[number]) {}有一个名为的数字参数a_0,这不理想)

  5. 我们可以使用自定义条件类型建立基于存在所需的签名payloadmeta

  6. 由于包含未解析类型参数的条件类型在编写实现时非常糟糕,因此我们将对内部函数使用单独的实现签名。

将所有这些东西放在一起,我们得到:


type Payload<T> = T extends { payload: infer P } ? P : undefined;
type Metadata<T> = T extends { meta: infer M } ? { meta: M } : undefined;
type CreateActionParameteres<A> =  /*4*/ Parameters<
  /*5*/ A extends { payload: infer P, meta: infer M } ? /*4*/ (payload: P, meta: { meta: M }) => void :
  /*5*/ A extends { payload: infer P } ? /*4*/ (payload: P) => void :
  /*5*/ A extends { meta: infer M } ? /*4*/ (payload: undefined, meta: { meta: M }) => void :
  () => void>

const createAction = <T extends AllActions['type'] /*1*/ >(type: T) =>
{
  function inner(...a: CreateActionParameteres</*2*/ Extract<AllActions, { type: T }>>): /*2*/ Extract<AllActions, { type: T }>
  function inner(payload?: Payload<AllActions>, meta?: Metadata<AllActions>) { /*6*/
    return {
      type,
      ...payload && { payload },
      ...meta && { meta }
    };
  }
  return inner;
}

游乐场链接

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

javascript:函数中的可选第一个参数

R:使用现存的(...)参数查找提供给函数的变量

如何将参数传递给第一个参数为self的python函数?

必须以MyModel实例作为第一个参数来调用未绑定方法save()

根据第一个参数在函数内部创建新函数

如何创建一个带有多个参数的函数并为该函数提供第一个参数的宏?

Typescript从函数中删除第一个参数

用返回类型与其第一个参数相同的函数来定义函数的正确方法是什么

引用当前函数的第一个参数类型

根据对象从第一个参数推断第二个参数

如何从函数参数类型中省略第一个参数?

std :: vector :: insert,可以将end作为第一个参数来调用吗?

当iterable不是函数的第一个参数时

如何从第二个引用函数的第一个参数?(python 2.7)

使用提供给另一个命令的参数来别名化一个命令

JS中的文本函数第一个参数(_)

fgets函数的第一个参数

如何修复TypeError:必须使用Dropper实例作为第一个参数来调用未绑定方法

Shell函数仅使用第一个参数

如何删除函数的第一个参数?

我该如何制作一个带有参数的函数,并且在执行该函数时,它会提示您提供给该函数的任何内容?

将 Observable 的参数提供给返回 Observable 的函数

如何使 apply() 在函数的一个参数(不是第一个)中传递对象?

TypeScript:如何根据第一个参数省略函数中的第二个参数

检查提供给另一个可调用参数的参数

改变第一个参数类型的增强函数?

根据提供给蛇形管道的参数,有条件地执行一个或另一个规则

函数的宏驱动条件第一个参数

如何获取函数的第一个参数的类型?