如何让TypeScript工厂函数根据入参自动收窄返回值类型?
解决TypeScript工厂函数根据brand收窄返回类型的问题
你的问题核心在于原函数的参数类型无法让TypeScript建立brand与对应车型的关联关系,导致返回值无法自动收窄到具体的Car子类型。下面是具体的解决思路和修改后的代码:
解决方案步骤
- 定义品牌到车型的映射类型,明确每个brand对应的具体Car子类型,让TypeScript能通过brand直接定位到目标类型
- 使用泛型约束函数的入参和返回值,将输入的brand与返回的车型类型绑定
- 调整参数类型,确保传入的overrides只能对应目标车型的可选属性,避免类型不兼容
修改后的完整代码
type ToyotaCar = { brand: 'toyota' isCool: true } type LamboCar = { brand: 'lambo' isAwesome: false } type FordCar = { brand: 'ford' isFast: false } // 定义品牌到车型的映射类型,核心关联逻辑 type CarBrandMap = { toyota: ToyotaCar lambo: LamboCar ford: FordCar } type Car = ToyotaCar | LamboCar | FordCar const mockToyota: ToyotaCar = { brand: 'toyota', isCool: true } const mockLambo: LamboCar = { brand: 'lambo', isAwesome: false } const mockFord: FordCar = { brand: 'ford', isFast: false } // 泛型约束brand为CarBrandMap的键,绑定入参和返回值类型 const carFactory = <B extends keyof CarBrandMap>( options: Partial<CarBrandMap[B]> & { brand: B } ): CarBrandMap[B] => { const { brand, ...overrides } = options switch (brand) { case 'toyota': return { ...mockToyota, ...overrides } as CarBrandMap[B] case 'ford': return { ...mockFord, ...overrides } as CarBrandMap[B] case 'lambo': return { ...mockLambo, ...overrides } as CarBrandMap[B] default: throw new Error(`不支持的品牌:${brand}`) } } // 类型推导正常,ford会被识别为FordCar类型 const ford = carFactory({ brand: 'ford' }) ford.isFast // 无类型报错,属性访问正常 // 测试自定义属性场景,TypeScript会自动校验属性合法性 const customToyota = carFactory({ brand: 'toyota', isCool: true }) // 若传入不属于ToyotaCar的属性(如isFast),TypeScript会直接报错
关键说明
- CarBrandMap映射类型:这是实现类型联动的核心,它将每个brand字符串与对应的Car子类型一一绑定,让TypeScript能明确识别brand对应的具体类型。
- 泛型约束:通过
<B extends keyof CarBrandMap>限制传入的brand必须是映射类型中的合法键,同时将参数的overrides类型和返回值类型与B关联,实现了基于输入的类型推导。 - 类型断言:函数内部的
as CarBrandMap[B]是因为TypeScript在switch分支中无法自动将返回值与泛型B关联,手动断言后即可让类型推导正常工作。
内容的提问来源于stack exchange,提问作者ShonJon
相关产品推荐
相关产品推荐

