如何通过键名从主/子对象获取属性?TypeScript类型问题
问题分析与解决方案
核心问题在于原函数的泛型约束错误,且未保证传入的key同时存在于主对象和coAuthors子对象中,导致TypeScript无法确认key能安全索引子对象。
第一步:优化接口定义(可选但更合理)
原接口中coAuthors的元组写法不符合实际场景,改成数组并复用Author属性定义,避免重复代码:
interface Author { id?: number; firstName?: string; lastname?: string; age?: number; // 子作者无需coAuthors属性,且所有字段必填 coAuthors?: Array<Required<Omit<Author, 'coAuthors'>>>; }
第二步:重构getByKeyName函数
调整泛型约束,确保key同时属于主对象和子对象的键,修正类型判断逻辑:
const getByKeyName = <T extends { coAuthors?: Array<U> }, U, K extends keyof T & keyof U>( item: T, key: K ) => { // 优先取主对象的属性值 const mainValue = item[key]; if (mainValue !== undefined) { return mainValue; } // 检查子作者数组是否有效 if (item.coAuthors?.length) { return item.coAuthors[0][key]; } // 兜底返回0(若需灵活兜底值,可新增参数) return 0 as T[K] | U[K]; };
调用示例
const author: Author = { id: undefined, coAuthors: [{ id: 101, firstName: "Jane", lastname: "Doe", age: 30 }] }; const authorId = getByKeyName(author, 'id'); // 类型为number | undefined,值为101 const authorName = getByKeyName(author, 'firstName'); // 类型为string | undefined,值为"Jane"
关键优化点
- 精准泛型约束:通过
K extends keyof T & keyof U确保key在主对象和子对象中都存在,彻底解决索引错误。 - 类型复用:用
Required<Omit<Author, 'coAuthors'>>定义子作者类型,既避免重复编码,又保证子作者字段必填。 - 逻辑清晰化:拆分判断逻辑,先检查主对象值,再验证子作者数组,最后兜底,代码可读性更强。
内容的提问来源于stack exchange,提问作者Victor
相关产品推荐
相关产品推荐

