我正在尝试做一些感觉荒谬的事情,但我已经非常接近了,我觉得它一定是可能的,我只是不太明白。
我正在尝试创建一个通用函数类型,以便分配函数类型
const typedFunction: Generic<
SomeObject,
['keys', 'in', 'that', 'object']
>;
将生成一个函数,其参数的类型准确:
(
arg0: typeof SomeObject['keys'],
arg1: typeof SomeObject['in'],
arg2: typeof SomeObject['that'],
arg3: typeof SomeObject['object']
)
我已经找到了两个接近但不完全的解决方案;
1.
declare type SomeGeneric<
T,
Params extends (T[keyof T])[]
> = (...args: Params) => ReturnType;
这保留了顺序,但迫使我以一种非常丑陋的方式指定参数:
const someFunction: SomeGeneric<
SomeObject,
[SomeObject['keys'], SomeObject['in'], ...]
> = (arg0, arg1, arg2, arg3) => { ... };
这显然冗长到无用的程度,因为我可以直接这样指定它们。
2.
declare type SomeGeneric<
T,
Params extends (keyof T)[]
> = (...args: T[Params[number]][]) => ReturnType;
但是,由于
Params[number]
引用 Params
的 any成员,这会将
SomeGeneric<SomeObject, ['keys', 'in', 'that', 'object']>
的每个参数转换为 SomeObject['keys'] | SomeObject['in'] | ...
的联合类型
我想知道的是,是否有某种方法可以指定我希望通过提供的键按顺序访问
SomeObject
,例如...args: SomeObject[...Params[number]]
(如果这种语法不是无意义的话)。您需要使用
映射类型来映射Params
中的元素。对于每个索引
I
,您可以获得数组元素 Params[I]
,可用于 T
。请注意,从 3.1 开始,使用映射类型来映射元组也会生成元组。这在这里很重要,因为扩展参数类型必须是元组类型。
declare type SomeGeneric<
T,
Params extends (keyof T)[]
> = (...args: { [I in keyof Params]: T[Params[I]] }) => void;
type Test = {
a: string
b: number
c: Date
}
const someFunction: SomeGeneric<Test, ["a", "b", "c"]> = (
arg0, // string
arg1, // number
arg2 // Date
) => {}