TypeScript中如何强制类或对象必须包含指定数据类型的属性?
核心实现
先给出满足需求的通用工具类型:
// 筛选出类型T中所有值为Function类型的键 type FunctionKeys<T> = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T] // 约束类型T必须至少包含一个Function类型的属性 type AtLeastOneFunction<T> = FunctionKeys<T> extends never // 无函数属性时返回不兼容类型触发报错,提示内容可自定义 ? { __error: "当前类型必须至少存在一个Function类型的字段" } : T
场景使用示例
1. 约束对象字面量
通过封装工具函数实现自动类型推导+约束:
function defineStruct<T>(input: AtLeastOneFunction<T>) { return input } // ✅ 合法:存在greet函数,其他属性类型不受限制 const validObj = defineStruct({ msg: "Hello", count: 10, isEnable: true, list: [1,2,3], greet: () => console.log("hi") }) // ❌ 报错:不存在任何Function类型属性 const invalidObj = defineStruct({ msg: "Hello", count: 10 })
2. 约束类
两种常用校验方式:
方式1:类声明时直接校验
// ✅ 合法:存在greet方法 class Foo implements AtLeastOneFunction<Foo> { msg = "Hello!" greet() { console.log(this.msg) } } // ❌ 报错:无Function类型属性 class Bar implements AtLeastOneFunction<Bar> { msg = "Hello!" }
方式2:批量约束构造函数类型
适合统一校验多个类是否符合要求的场景:
type ValidClass = new (...args: any[]) => AtLeastOneFunction<any> const ValidFoo: ValidClass = Foo // ✅ 合法 const InvalidBar: ValidClass = Bar // ❌ 报错
原代码错误原因
你之前写的索引签名[index: string]: Function要求所有属性的类型都必须是Function,完全不符合「允许其他任意类型属性,仅要求至少一个函数」的需求,所以会出现类型不匹配报错。
相关知识点说明
- 映射类型:通过
[K in keyof T]遍历类型的所有键,可对每个键的类型做自定义处理 - 条件类型:通过
T extends U ? X : Y语法实现类型的逻辑判断,这里用来筛选值为Function的键、判断是否存在符合要求的键 - 泛型约束:通过泛型动态适配不同结构的对象/类,不需要提前写死类型结构
内容的提问来源于stack exchange,提问作者Grizzly
相关产品推荐
相关产品推荐

