TypeScript结合泛型与联合类型按标识返回对应名称的实现问题
问题原因
你当前的写法中,TypeScript 无法通过传入的isPerson参数值自动将泛型T缩窄到对应的Person或Animal子类型,因此返回值会被推导为LivingBeing["name"]的全量联合类型,达不到你要的类型区分效果。
解决方案1:函数重载(最直观易用)
通过定义不同入参对应的返回值重载签名,TS 会在调用时自动匹配对应的重载规则,推导正确的返回类型:
interface Person { name: "Peter" | "Robert"; age: number; isPerson: true } interface Animal { name: "Jerry" | "Tom"; age: number; isPerson: false } type LivingBeing = Person | Animal // 重载签名:入参为true时返回Person的name类型 function getRandomName(isPerson: true): Person["name"] // 重载签名:入参为false时返回Animal的name类型 function getRandomName(isPerson: false): Animal["name"] // 内部实现签名 function getRandomName(isPerson: boolean): LivingBeing["name"] { const names = isPerson ? ["Peter", "Robert"] : ["Jerry", "Tom"] return names[Math.floor(Math.random() * names.length)]; } const person = getRandomName(true) // 自动推导为 "Peter" | "Robert" const animal = getRandomName(false) // 自动推导为 "Jerry" | "Tom"
解决方案2:泛型+条件类型
如果希望保留泛型写法,可以直接通过条件类型关联入参布尔值和返回值的对应关系:
function getRandomName<T extends boolean>(isPerson: T): T extends true ? Person["name"] : Animal["name"] { const names = isPerson ? ["Peter", "Robert"] : ["Jerry", "Tom"] return names[Math.floor(Math.random() * names.length)] as any }
两种方案都可以实现调用getRandomName(true)时返回值仅为"Peter" | "Robert"的预期效果。
内容的提问来源于stack exchange,提问作者Max García
相关产品推荐
相关产品推荐

