TypeScript调用点基于联合类型收窄类型参数的实现方案
TypeScript函数接收联合类型成员时返回匹配入参的具体子类型实现方法
问题场景
定义Animal联合类型,由Dog、Cat两个具体类型组成,二者均包含name属性。初始实现的nameAnimal函数入参、返回值均标注为Animal类型,代码如下:
type Animal = Dog | Cat type Dog = { name: string // 其余Dog类型属性 } type Cat = { name: string // 其余Cat类型属性 } function nameAnimal(animal: Animal, name: string): Animal { animal.name = name return animal } function handleDog(dog: Dog) { // Dog类型专属处理逻辑 }
这种写法存在类型问题:当传入Dog类型的变量fido调用nameAnimal(fido, 'Fido')时,返回值类型为Animal联合类型,无法直接传入要求参数为Dog类型的handleDog函数,会触发类型校验报错。
同类逻辑在Java中可以通过带上界约束的泛型实现,参考代码如下:
public static <T extends Animal> T nameAnimal(T animal, String name) { animal.name = name; return animal; }
实现方案
该需求不受TypeScript联合类型固有特性限制,完全可以通过泛型约束实现同等效果,核心是让泛型类型受对应规则约束,入参和返回值均使用该泛型类型,基础实现代码如下:
function nameAnimal<T extends { name: string }>(animal: T, name: string): T { animal.name = name return animal }
方案扩展调整
- 上述基础写法已覆盖绝大多数常规使用场景,仅约束入参必须包含字符串类型的
name属性,不会丢失入参其他自定义属性的类型信息 - 若需要严格限制入参只能为
Animal联合类型的成员,仅需将泛型上界从{ name: string }调整为Animal即可,调整后代码:
function nameAnimal<T extends Animal>(animal: T, name: string): T { animal.name = name return animal }
内容的提问来源于stack exchange,提问作者Ian Melendez
相关产品推荐
相关产品推荐

