能否在编译时提取TypeScript类型的键?
问题解答
首先明确:原生TypeScript无法直接通过KeysOf<FooBar>()这种语法从编译时类型提取运行时的键数组。因为TypeScript的类型系统完全是编译时概念,编译后所有类型信息都会被擦除,不会在最终的JavaScript代码中留下任何痕迹,所以没办法直接从类型生成运行时可用的数组。
不过有几种可行的替代方案,能实现“让类型和运行时键保持一致”的需求:
方案1:从运行时对象推导类型(推荐)
先定义运行时的对象,再通过typeof推导对应的类型,同时直接从对象提取键数组:
// 先定义运行时对象 const fooBarSample = { foo: 3, bar: 2 }; // 从对象推导类型 type FooBar = typeof fooBarSample; // 获取类型安全的键数组,用类型断言确保类型正确 const keys = Object.keys(fooBarSample) as Array<keyof FooBar>; function isFooBar(obj: any): boolean { return keys.every(key => key in obj); }
这种方案的优势是类型和运行时数据完全同步,不需要手动维护两份内容,避免不一致。
方案2:用枚举关联类型与运行时
枚举在TypeScript编译后会保留运行时表示,所以可以用枚举定义键,再基于枚举构建类型:
// 定义枚举作为键的唯一来源 enum FooBarKeys { Foo = 'foo', Bar = 'bar' } // 基于枚举构建类型 type FooBar = { [FooBarKeys.Foo]: number; [FooBarKeys.Bar]: number; }; // 从枚举提取运行时键数组 const keys = Object.values(FooBarKeys); function isFooBar(obj: any): boolean { return keys.every(key => key in obj); }
这种方案适合需要明确管理键集合的场景,枚举可以统一控制键的命名和值。
方案3:自定义编译转换器(进阶)
如果项目中有大量类似需求,可以使用第三方工具(如ts-transformer-keys),它能在编译阶段自动从类型生成对应的运行时键数组。不过这种方式需要修改TypeScript的编译配置,添加自定义transformer,依赖特定的构建工具链(如webpack、Rollup)。
示例配置后用法:
import { keys } from 'ts-transformer-keys'; type FooBar = { foo: number; bar: number; }; // 编译时会自动生成["foo", "bar"]的运行时数组 const keys = keys<FooBar>(); function isFooBar(obj: any): boolean { return keys.every(key => key in obj); }
注意:这不是TypeScript原生支持的功能,需要额外配置工具链。
内容的提问来源于stack exchange,提问作者Alessandro Tornesi
相关产品推荐
相关产品推荐

