如何为TypeScript的carryOver函数添加类型,让输出包含输入和返回对象属性?
为carryOver函数添加精确的TypeScript类型定义
原函数实现如下:
carryOver = <T extends Record<string, any>>(fun: (obj: T) => Record<string, any>) => (obj: T) => Object.assign({}, obj, fun(obj))
示例用法:
const makeGreeting = ({name, title}) => ({greeting: `Hello ${title} ${name}`}) const person = {name: "Thomas", title: "Dr."} const personWithLabel = carryOver(makeGreeting)(person) // 期望类型:{ name: string; title: string; greeting: string }
需求是让carryOver的返回值类型同时包含输入对象A的所有属性,以及传入函数返回的新对象B的所有属性。
解决方案:使用双泛型参数与交叉类型
我们可以通过引入第二个泛型参数捕获传入函数返回的对象类型,再通过交叉类型(&)合并输入对象类型和新对象类型,实现精确的类型推导:
const carryOver = <T extends Record<string, unknown>, U extends Record<string, unknown>>( fun: (obj: T) => U ) => (obj: T): T & U => Object.assign({}, obj, fun(obj))
类型说明
T:表示输入对象的类型,约束为Record<string, unknown>(比any更安全,保留类型检查能力)U:表示传入函数fun返回的新对象的类型,同样约束为字符串键的对象类型- 返回值类型
T & U:直接合并输入对象和新对象的所有属性,TypeScript会自动推导两者的完整属性集合
验证示例
用原示例测试,TypeScript会自动正确推导类型:
const makeGreeting = ({name, title}: {name: string; title: string}) => ({ greeting: `Hello ${title} ${name}` }) const person = {name: "Thomas", title: "Dr."} const personWithLabel = carryOver(makeGreeting)(person) // 此时personWithLabel的类型被正确推导为: // { name: string; title: string; greeting: string } // 访问personWithLabel.greeting时会有完整的类型提示
即使省略makeGreeting的参数类型,TypeScript依然能通过person的类型反向推导T,进而得到U的类型,最终合并出正确的返回类型。
内容的提问来源于stack exchange,提问作者Adam B.
相关产品推荐
相关产品推荐

