如何在TypeScript中让对象内函数参数类型依赖另一属性的值?
在TypeScript中实现对象内函数参数类型依赖另一属性的值
要实现Column接口中render函数的value参数类型依赖dataIndex属性的值,核心是让TypeScript能根据每个对象的具体dataIndex值,精确推断对应的value类型。原接口的问题在于泛型参数是联合类型,导致render参数类型无法区分具体场景,下面是可行的解决方案:
方案一:映射类型生成联合类型
通过映射类型遍历所有可能的dataIndex值,生成每个值对应的具体Column类型,最终得到所有类型的联合。这种方式能让TypeScript自动为每个对象推断正确类型:
type Column<T = any> = { [P in keyof T | string]: { dataIndex: P; render?: (value: P extends keyof T ? T[P] : any) => any; }; }[keyof T | string];
验证示例
const dataSource = [{ a: 1, b: '2' }] as const; type Item = typeof dataSource[0]; const columns: Column<Item>[] = [ { dataIndex: 'a', render(value) { // value 自动推断为 number 类型 console.log(value.toFixed(2)); // 编译正常,支持number方法 } }, { dataIndex: 'b', render(value) { // value 自动推断为 string 类型 console.log(value.toUpperCase()); // 编译正常,支持string方法 } }, { dataIndex: 'c', render(value) { // value 自动推断为 any 类型 console.log(value); // 无类型限制 } }, ];
方案二:泛型接口+联合数组类型
如果偏好保留接口形式,可以定义泛型Column接口,再通过联合类型定义数组类型:
interface Column<T, P extends keyof T | string> { dataIndex: P; render?: (value: P extends keyof T ? T[P] : any) => any; } // 定义包含所有场景的数组类型 type Columns<T> = Array<Column<T, keyof T> | Column<T, Exclude<string, keyof T>>>;
使用示例
const columns: Columns<Item> = [ // 同方案一示例,类型推断效果一致 ];
原接口问题说明
原接口中P被定义为keyof T | string联合类型,创建数组时TypeScript会将P推断为整个联合类型,导致render的value类型变成T[keyof T] | any,无法区分每个dataIndex对应的具体类型。上述方案通过让每个对象对应单个具体的P值,实现了参数类型的精准依赖。
内容的提问来源于stack exchange,提问作者aweiu
相关产品推荐
相关产品推荐

