如何为getParameters函数定义基于入参的严格返回类型?
解决方案
要实现根据入参paramNames的结构严格约束getParameters的返回类型,你需要借助TypeScript泛型和递归工具类型来推导键的集合,具体步骤如下:
1. 明确基础类型定义
首先完善RecursiveObject的类型,确保它能描述嵌套的参数名结构:
// 描述嵌套的参数名对象,叶子节点可用空字符串仅用于定义结构 type RecursiveObject = { [key: string]: string | RecursiveObject; };
2. 定义键提取工具类型
创建FlattenKeys工具类型,递归提取数组元素或嵌套对象的所有路径键:
type FlattenKeys<T> = // 入参为字符串数组时,直接取数组元素的联合类型 T extends string[] ? T[number] : // 入参为嵌套对象时,递归拼接路径生成键 T extends RecursiveObject ? { [K in keyof T]: T[K] extends string ? K : `${K}.${FlattenKeys<T[K]>}` }[keyof T] : never;
3. 改造ParamValuesDictionary与函数定义
将ParamValuesDictionary改为泛型类型,通过FlattenKeys<T>推导严格的键集合,同时给getParameters添加泛型约束:
// 泛型类型,键完全由入参的参数名推导而来 type ParamValuesDictionary<T> = { [K in FlattenKeys<T>]: string; }; // 泛型函数,约束入参为字符串数组或RecursiveObject function getParameters<T extends string[] | RecursiveObject>(paramNames: T): ParamValuesDictionary<T> { // 原有参数加载逻辑保持不变,类型会自动推导 const result: Record<string, string> = {}; // 示例遍历逻辑(实际替换为你的业务实现) const traverse = (names: any, prefix = '') => { if (Array.isArray(names)) { names.forEach(key => result[key] = ''); } else { Object.entries(names).forEach(([key, value]) => { const fullKey = prefix ? `${prefix}.${key}` : key; typeof value === 'string' ? result[fullKey] = '' : traverse(value, fullKey); }); } }; traverse(paramNames); return result as ParamValuesDictionary<T>; }
4. 使用示例
现在函数返回类型会严格对应入参的参数名,超出范围的键会触发类型报错:
// 传入字符串数组:返回类型为 { name: string; age: string } const params1 = getParameters(['name', 'age']); params1.name; // 合法 params1.gender; // 类型报错:不存在该属性 // 传入嵌套对象:返回类型为 { 'user.name': string; 'user.address.city': string; 'role': string } const params2 = getParameters({ user: { name: '', address: { city: '' } }, role: '' }); params2['user.address.city']; // 合法 params2['user.phone']; // 类型报错:不存在该属性
内容的提问来源于stack exchange,提问作者Andrei Khotko
相关产品推荐
相关产品推荐

