如何让TypeWithAddedProperty支持数组类型的条件泛型处理?
解决方案:用条件类型适配数组与单个对象场景
当然可以搞定这个问题!咱们的核心目标就是让TypeWithAddedProperty能智能区分输入是单个对象还是数组,分别返回对应的扩展类型。
第一步:修改TypeWithAddedProperty为条件类型
我们可以利用TypeScript的条件类型+类型推断,来实现根据输入类型动态调整返回类型:
export type TypeWithAddedProperty<T> = // 如果T是数组类型,提取数组元素类型U,返回元素带新增属性的数组 T extends Array<infer U> ? Array<U & { addedProperty: string }> : // 非数组类型,直接返回原类型与新增属性的交叉类型 T & { addedProperty: string };
这里的infer U是关键,它会自动提取数组的元素类型U,然后我们给U加上addedProperty后再重新包裹成数组,完美匹配数组场景的预期。
第二步:修正函数的参数类型与返回断言
接下来需要给函数的data参数指定类型T,同时为了让TypeScript的控制流分析能正确匹配条件类型的返回,我们需要在两个分支里加上类型断言:
function addSomeStuff<T>(data: T): TypeWithAddedProperty<T> { if (Array.isArray(data)) { return data.map(element => { return { ...element, addedProperty: 'something' }; }) as TypeWithAddedProperty<T>; } else { return { ...data, addedProperty: 'something' } as TypeWithAddedProperty<T>; } }
验证效果
现在不管是传入单个对象还是数组,返回类型都符合预期了:
// 单个对象场景 const user = { id: 1, name: 'Alice' }; const extendedUser = addSomeStuff(user); // extendedUser 类型:{ id: number; name: string } & { addedProperty: string } // 数组场景 const users = [{ id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' }]; const extendedUsers = addSomeStuff(users); // extendedUsers 类型:Array<{ id: number; name: string } & { addedProperty: string }>
为什么需要类型断言?
TypeScript的控制流分析虽然强大,但对于条件类型的复杂推断有时候会“转不过弯来”——它没法自动识别map返回的数组正好是条件类型里定义的Array<U & {addedProperty: string}>,所以我们需要用as TypeWithAddedProperty<T>来帮它确认返回值类型的正确性。
内容的提问来源于stack exchange,提问作者cuddlemeister
相关产品推荐
相关产品推荐

