如何定义含on前缀函数属性的TypeScript对象类型?
如何定义符合特定规则的对象类型?
需求:定义一个对象类型,满足以下规则:
- 键的类型可以是字符串或数字
- 所有以
on为前缀的字符串键,对应的值必须是(...args: any[]) => any类型的函数 - 其他键(非
on前缀的字符串/数字键)对应的值类型为string | number
原尝试代码(报错):
type ValidProps = { [K in string]: K extends `on${string}` ? (...args: any[]) => any : (string | number) }; const props: ValidProps = { a: "foo", b: 1, onC: () => {}, // TS报错 };
问题原因
原代码的索引签名对所有string类型的键做条件判断,但TypeScript的索引签名要求所有符合键类型的属性必须满足对应的类型约束,这导致onC这类键同时被要求既是string | number(来自string键的默认约束)又是函数(来自条件判断),类型冲突引发报错。
正确实现方式
使用交叉类型拆分两种键的约束,分别定义普通键和on前缀键的规则:
type ValidProps = // 处理非on前缀的字符串/数字键:值为string | number { [K in string | number]: K extends `on${string}` ? never : string | number; } & // 处理on前缀的字符串键:值为函数 { [K in `on${string}`]: (...args: any[]) => any; };
验证示例
// 合法示例:符合所有规则 const props: ValidProps = { a: "foo", b: 1, 123: 456, // 支持数字键 onC: () => {}, onD: (x: number, y: string) => `${x}${y}`, // 函数可以自定义参数和返回值 }; // 错误示例(会触发TS类型检查报错): // const invalidProps: ValidProps = { // onE: "not a function", // on前缀键的值不是函数 // c: () => {}, // 非on前缀键的值是函数,不符合要求 // };
补充说明
- 第一个索引签名中,
K extends \on${string}` ? never : string | number的作用是排除on`前缀的字符串键,避免和第二个索引签名冲突 - 交叉类型会合并两个类型的约束,确保对象的每个键都符合对应的规则
内容的提问来源于stack exchange,提问作者bitsoverflow
相关产品推荐
相关产品推荐

