我可以使用映射条件类型从记录类型映射到函数类型吗?

时间:2018-03-31 16:06:57

标签: typescript mapped-types

在Typescript中给出以下类型

type MyType = {
    foo: int,
    bar: string
}

我可以定义一个映射(preferriby使用映射条件类型),以便我得到

type MyTypeFn = (foo: int, bar: string) => MyType

1 个答案:

答案 0 :(得分:1)

不是真的。无法以任何可预测或可用的顺序枚举对象的键。你可以用某些东西编程,但你必须从一个更易于操作的类型开始,如下所示:

type MySchema = [['foo', number], ['bar', string]]

这是一个2元组的元组,表示类型中的键值对。然后,您可以使用(TSv2.8及更高版)类型函数合成MyType,例如:

type MakeMyType<S extends [string, any][], M = S[number]> = 
  { [K in S[number][0]]: M extends [K, any] ? M[1] : never }

您可以验证:

type MyType = MakeMyType<MySchema>
// inspects as { foo: number; bar: string }

然后你可以使用类型函数合成MyTypeFn,例如:

type MakeMyFunction<S extends [string, any][], L = S['length'], T = MakeMyType<S>> =
  L extends 0 ? () => T :
  L extends 1 ? (a0: S[0][1]) => T :
  L extends 2 ? (a0: S[0][1], a1: S[1][1]) => T :
  L extends 3 ? (a0: S[0][1], a1: S[1][1], a2: S[2][1]) => T :
  L extends 4 ? (a0: S[0][1], a1: S[1][1], a2: S[2][1], a3: S[3][1]) => T :
  L extends 5 ? (a0: S[0][1], a1: S[1][1], a2: S[2][1], a3: S[3][1], a4: S[4][1]) => T :
  L extends 6 ? (a0: S[0][1], a1: S[1][1], a2: S[2][1], a3: S[3][1], a4: S[4][1], a5: S[5][1]) => T :
  (...args: S[number][1][]) => T

请注意,如果没有编程方式来执行可变长度参数列表,那么您可以做的最好的事情就是将案例设置为如上所述的固定最大长度。我们来验证:

type MyTypeFn = MakeMyFunction<MySchema>
// inspects as (a0: number, a1: string) => { foo: number; bar: string; }

是的,参数名称也会丢失(foobar变为a0a1)。这不会影响函数签名的类型兼容性,其中参数名称不重要。但我猜你在使用或实现这个功能时想要这些参数名称。如果是这样,那就是另一个“不是真的”。

所以这是一种漫长的说法,即多次说“不是真的”。哦,好吧,无论如何它可能还有一些帮助。祝你好运!