我有一个数组类,并希望提取所有的方法到一个类型的联盟。
例如:
class A{
getBooks(): Book[]{}
getBook(): Book{}
}
class B{
getUsers(): User[]{}
getUser(): User{}
getBooksOfUser(userId: string)Book[]{}
}
我想有一个类型,其中有所有的方法,像这样:
type allMethods = "getBooks" | "getBook" | "getUsers" | "getUser" | "getBooksOfUser";
我尝试了几种不同的东西,但无法得到它的工作:
const testResolvers = <const> [A, B]
type ExtractFunctionKeys<T> = { [P in keyof T]-?: T[P] extends Function ? P : never}[keyof T]
export type ValuesOf<T extends any[]>= ExtractFunctionKeys<T[number]>;
type Foo = ValuesOf<typeof testResolvers>;
谢谢你的帮助!
1条答案
按热度按时间gfttwv5a1#
在上述尝试中有两个主要问题:
T[number]
(indexed access type)产生T
元组/数组中每种类型的 * 联合 *;当使用属于这种联合的变量时,TypeScript仅将键(共享键)的 * 交集 * 保持为有效;在您的示例中,A | B
没有公共密钥,因此keyof (A | B)
已经是never
(即,即使没有过滤方法)typeof testResolvers
是readonly [typeof A, typeof B]
,即它把typeof
操作符分配给元组元素,我们得到类的类型 constructor 而不是实际的类类型;那么当访问它们的密钥时(例如使用keyof typeof A
),我们得到的只是"prototype"
问题1:我们想要一个 * 交集 *,而不是一个 union,TypeScript会将索引键的 union(交集任何元素中的所有索引键)保持为有效。没有简单的方法可以从Tuple建立这样的交集(我们无法使用索引存取表示法)。但它仍然是可行的,例如:
问题2:要从构造函数类型中取回 class 类型,我们只需要确保访问
"prototype"
属性,通常是再次通过索引访问。如果需要,我们甚至可以构建一个helper类型来有条件地执行转换:然后,我们可以将这些辅助类型插入到链中,以获得提取元组中所有类的方法的并集的所需行为:
Playground链接