我可以使用映射条件类型从记录类型映射到函数类型吗?
Can I map from a record type to a function type using mapped conditional types?
在 Typescript 中给定以下类型
type MyType = {
foo: int,
bar: string
}
我可以定义一个映射(最好使用映射的条件类型)以便我得到
type MyTypeFn = (foo: int, bar: string) => MyType
不是真的。无法以任何可预测或可用的顺序枚举对象的键。你可以一些程序化的东西,但你必须从更容易操作的类型开始,像这样:
type MySchema = [['foo', number], ['bar', string]]
这是一个 2 元组的元组,表示您的类型中的 key-value 对。然后您可以使用(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
请注意如何没有程序化的方法来执行 variable-length 参数列表,因此您能做的最好的事情就是像上面那样将 case 设置为某个固定的最大长度。让我们验证一下:
type MyTypeFn = MakeMyFunction<MySchema>
// inspects as (a0: number, a1: string) => { foo: number; bar: string; }
是的,参数名称也丢失了(foo
和 bar
变成了 a0
和 a1
)。这不会影响函数签名的类型兼容性,其中参数名称并不重要。但我猜你希望这些参数名称在使用或实现函数时进行提示。如果是这样,那就是另一个 "not really".
所以这是一个很长的 drawn-out 多次表达 "not really" 的方式。哦,好吧,也许无论如何它都有一些帮助。祝你好运!
在 Typescript 中给定以下类型
type MyType = {
foo: int,
bar: string
}
我可以定义一个映射(最好使用映射的条件类型)以便我得到
type MyTypeFn = (foo: int, bar: string) => MyType
不是真的。无法以任何可预测或可用的顺序枚举对象的键。你可以一些程序化的东西,但你必须从更容易操作的类型开始,像这样:
type MySchema = [['foo', number], ['bar', string]]
这是一个 2 元组的元组,表示您的类型中的 key-value 对。然后您可以使用(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
请注意如何没有程序化的方法来执行 variable-length 参数列表,因此您能做的最好的事情就是像上面那样将 case 设置为某个固定的最大长度。让我们验证一下:
type MyTypeFn = MakeMyFunction<MySchema>
// inspects as (a0: number, a1: string) => { foo: number; bar: string; }
是的,参数名称也丢失了(foo
和 bar
变成了 a0
和 a1
)。这不会影响函数签名的类型兼容性,其中参数名称并不重要。但我猜你希望这些参数名称在使用或实现函数时进行提示。如果是这样,那就是另一个 "not really".
所以这是一个很长的 drawn-out 多次表达 "not really" 的方式。哦,好吧,也许无论如何它都有一些帮助。祝你好运!