TypeScript:能否自动为命名空间内所有接口生成判别式联合?
动态生成TypeScript命名空间内接口的判别式联合
嘿,这个需求我太懂了——每次新增接口都要手动更新联合类型确实有点烦,尤其是接口多的时候。针对你用的TypeScript 2.5/2.6版本,咱们可以利用TypeScript的类型系统特性,实现自动生成命名空间下所有接口的联合类型,不用每次手动修改!
实现方法
首先明确:TypeScript没有直接提供discriminatedUnion()这种现成的类型函数,但可以通过typeof和索引访问类型间接实现。具体代码如下:
export namespace Interfaces { export interface One { kind: "One" } export interface Two { kind: "Two" } export interface Three { kind: "Three" } // 以后新增接口直接加在这里就行,不用管下面的KnownInterfaces export interface Four { kind: "Four" } } // 动态生成所有接口的联合类型 type InterfacesMembers = typeof Interfaces; export type KnownInterfaces = InterfacesMembers[keyof InterfacesMembers];
原理说明
typeof Interfaces:获取到Interfaces命名空间的类型,这个类型会把所有导出的接口作为自身的属性(每个属性的类型就是对应的接口类型)。keyof InterfacesMembers:拿到所有接口名称的联合类型,比如上面的例子里就是"One" | "Two" | "Three" | "Four"。InterfacesMembers[keyof InterfacesMembers]:通过索引访问,把每个接口的类型提取出来,自动形成判别式联合类型。以后你在Interfaces里新增任何接口,KnownInterfaces都会自动更新,完全不用手动修改。
版本兼容性
这个方法在TypeScript 2.1及以上就支持了,你当前用的2.5完全没问题,升级到2.6当然也可以正常使用。
小提醒:如果你的
Interfaces命名空间以后导出了非接口的成员(比如变量、函数),这个方法会把它们也包含到联合类型里。所以如果要保持纯净,尽量让这个命名空间只导出接口就行。如果以后升级到TypeScript 2.8+,还可以用条件类型过滤掉非接口成员,但目前你的版本暂时不需要这一步。
内容的提问来源于stack exchange,提问作者user310988
相关产品推荐
相关产品推荐

