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

如何约束函数参数(对象)遵循特定键名规则?

实现TypeScript中对对象键名和值类型的双重约束

要同时约束selectors对象的键名格式(必须为select${Capitalize<string>})和值类型(必须是Selector),可以通过TypeScript的模板字面量类型、映射类型和泛型约束来实现,具体步骤如下:

1. 定义基础类型

首先明确Selector的类型定义:

// 定义Selector类型,接收可选的状态泛型S,返回unknown
type Selector<S = unknown> = (state: S) => unknown;

2. 创建键名验证工具类型

用模板字面量类型匹配符合要求的键名格式,排除仅select本身的情况:

// 验证键名是否符合 select${首字母大写字符串} 格式
type IsValidSelectorKey<K extends string> = 
  K extends `select${Capitalize<infer Rest>}` 
    ? Rest extends '' ? false : true // 排除仅"select"的键
    : false;

3. 构建约束型的Selectors类型

通过映射类型,对每个键进行校验:不符合规则的键,其值类型会被设为never(或自定义错误类型),触发TypeScript报错:

// 约束selectors的键和值:键必须符合格式,值必须是Selector
type ValidSelectors<T> = {
  [K in keyof T]: IsValidSelectorKey<string & K> extends true 
    ? Selector // 键合法时,值必须是Selector类型
    : never; // 键不合法时,值类型设为never,强制报错
};

4. 定义带泛型约束的函数

利用泛型让TypeScript自动推断传入的selectors类型,同时通过T extends ValidSelectors<T>强制约束:

function Foo<T extends ValidSelectors<T>>(arg: {
  name: string;
  selectors: T;
}) {
  // 函数业务逻辑
}

测试效果

当传入不符合规则的参数时,TypeScript会精准报错:

Foo({ 
  name: "Bar",
  selectors: {
    selectBuzz: () => {}, // ✅ 符合要求,无报错
    fizz: () => {}, // ❌ 键名不符合格式,触发报错
    selectFizz: '123', // ❌ 值类型不是Selector,触发报错
  }
});

优化错误提示(可选)

如果需要更友好的报错信息,可以把never替换为自定义错误类型:

type InvalidKeyMsg = "错误:键名必须遵循 `select${首字母大写字符串}` 格式(如selectBuzz)";
type InvalidValueMsg = "错误:值必须是Selector类型,即 (state: S) => unknown";

type ValidSelectors<T> = {
  [K in keyof T]: IsValidSelectorKey<string & K> extends true 
    ? T[K] extends Selector ? T[K] : InvalidValueMsg 
    : InvalidKeyMsg;
};

此时报错会直接显示自定义提示,更易理解。

内容的提问来源于stack exchange,提问作者Dellirium

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 02:52:27