You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 06:54:04