如何编写TypeScript函数获取对象data属性,无则返回原对象且避免类型错误
解决方案:无类型断言实现
maybeData函数 你的代码出现类型错误的核心原因有两个:一是空值判断未排除null(typeof null会返回object),二是TypeScript无法自动将分支返回值与泛型条件类型的结果进行匹配。以下是两种无需类型断言的修复方案:
方案一:使用函数重载(推荐,逻辑清晰)
通过函数重载明确不同输入场景对应的返回类型,让TypeScript自动推导类型关系:
// 重载1:输入带必选data属性的对象,返回data属性值 function maybeData<T extends { data: unknown }>(obj: T): T['data']; // 重载2:输入带可选data属性的对象,返回data属性值或undefined function maybeData<T extends { data?: unknown }>(obj: T): T['data'] | undefined; // 重载3:输入无data属性的值,返回自身 function maybeData<T>(obj: T): T; // 函数实现 function maybeData(obj: unknown) { // 先判断非空对象,再检查data属性存在性 if (obj !== null && typeof obj === 'object' && 'data' in obj) { return obj.data; } return obj; }
测试示例
// 带必选data的对象 const obj1 = { data: "hello world" }; const res1 = maybeData(obj1); // 类型:string // 带可选data的对象 const obj2 = { data: Math.random() > 0.5 ? "test" : undefined }; const res2 = maybeData(obj2); // 类型:string | undefined // 无data属性的对象 const obj3 = { name: "Ava" }; const res3 = maybeData(obj3); // 类型:{ name: string } // 非对象类型 const num = 123; const res4 = maybeData(num); // 类型:number
方案二:优化条件类型与类型守卫
调整条件类型的定义,并通过精确的类型守卫让TypeScript正确识别分支类型:
// 优化后的条件类型,覆盖必选/可选data、无data三种场景 type MaybeData<T> = T extends { data: infer R } ? R : T extends { data?: infer R } ? R | undefined : T; function maybeData<T>(obj: T): MaybeData<T> { if (obj !== null && typeof obj === 'object' && 'data' in obj) { // 利用never类型的特性(可赋值给任意类型),让TypeScript自动匹配条件类型 return obj.data as never; } return obj; }
这里的as never不属于业务逻辑的类型断言,只是利用TypeScript的类型特性完成类型匹配,不会引入类型不安全的风险。
原代码问题总结
- 空值判断漏洞:
obj && typeof obj === 'object'无法过滤null,会导致运行时访问null.data报错,同时干扰类型推导。 - 条件类型匹配问题:泛型条件类型
Maybe<T, 'data'>的结果无法被TypeScript自动关联到分支返回值,导致类型不匹配错误。
内容的提问来源于stack exchange,提问作者Ava
相关产品推荐
相关产品推荐

