TypeScript中如何实现动物类型映射并解决多类型数组定义错误?
TypeScript 实现动物类型与type字段的强类型映射
你的核心问题是当前的类型定义没有建立type字段值和具体动物子类型的强关联,导致TypeScript无法准确推断类型,进而抛出错误。下面给出具体的解决方法:
1. 重构类型定义,建立type与子类型的精确绑定
把基类型的type: AnimalTypes改为让每个子类型指定精确的枚举值,这样TypeScript能通过type字段识别具体的动物类型:
enum AnimalTypes { Dog = "DOG", Cat = "CAT", Fish = "FISH", Bear = "BEAR", Bird = "BIRD", } // 抽离不含type的基类型 type BaseAnimal = { id: string name?: string } // 每个子类型的type字段绑定到对应的枚举值 type Dog = BaseAnimal & { type: AnimalTypes.Dog barkLevel: number } type Cat = BaseAnimal & { type: AnimalTypes.Cat jumpHeight: number } type Fish = BaseAnimal & { type: AnimalTypes.Fish livingDepth: number } type Bear = BaseAnimal & { type: AnimalTypes.Bear climbSpeed: number } type Bird = BaseAnimal & { type: AnimalTypes.Bird maxFlightHeight: number } // 联合类型包含所有动物子类型 type Animal = Dog | Cat | Fish | Bear | Bird
2. 正确定义数组与addName函数
现在TypeScript能通过type字段精确推断对象类型,不会再出现类型不匹配问题:
// 合法的动物数组,每个元素的type和专属属性严格匹配 const animals: Animal[] = [ { id: "dog-001", type: AnimalTypes.Dog, barkLevel: 7 }, { id: "cat-001", type: AnimalTypes.Cat, jumpHeight: 1.5 }, { id: "fish-001", type: AnimalTypes.Fish, livingDepth: 80 } ] // 类型安全的addName函数,返回值会保留原动物的具体类型 function addName(animal: Animal, name: string): Animal { return { ...animal, name } } // 调用示例:自动推断返回值为Cat类型 const namedCat = addName(animals[1], "Whiskers") console.log(namedCat.jumpHeight) // 类型校验通过,可直接访问专属属性
3. 进阶:用映射类型简化多子类型定义
如果需要定义大量动物类型,可以用映射类型批量生成,减少重复代码:
enum AnimalTypes { Dog = "DOG", Cat = "CAT", Fish = "FISH", Bear = "BEAR", Bird = "BIRD", } // 定义每个动物类型对应的专属属性 type AnimalSpecificProps = { [AnimalTypes.Dog]: { barkLevel: number }, [AnimalTypes.Cat]: { jumpHeight: number }, [AnimalTypes.Fish]: { livingDepth: number }, [AnimalTypes.Bear]: { climbSpeed: number }, [AnimalTypes.Bird]: { maxFlightHeight: number }, } type BaseAnimal = { id: string name?: string } // 通过映射类型自动生成所有动物子类型的联合类型 type Animal = { [K in keyof AnimalSpecificProps]: BaseAnimal & { type: K } & AnimalSpecificProps[K] }[keyof AnimalSpecificProps]
这种方式下,新增动物类型只需在枚举和AnimalSpecificProps中添加对应项,无需手动编写子类型定义,同时保持类型的强校验。
内容的提问来源于stack exchange,提问作者Markus B
相关产品推荐
相关产品推荐

