将联盟T约束在不同的分支中

时间:2019-06-06 08:55:56

标签: typescript

是否可以检查方法主体中的泛型联合类型?

例如,我有

const stringIdentity = (original: string): string => {
    return original
}
const numIdentity = (original: number): number => {
    return original
}

const identity = <T = string | number>(original: T): T => {
    if (typeof original === 'string') {
        return stringIdentity(original) // <-- error on this line
    } 
    if (typeof original === 'number') {
        return numIdentity(original)    // <-- error on this line
    }
}

游乐场here

在每个分支中我都遇到错误*

  

类型'string'不能分配给类型'T'

作为一个人,我可以看到T是顶部分支中的字符串,并且我应该能够安全地返回字符串。有办法说服编译器吗?


*或“键入'数字'...”

2 个答案:

答案 0 :(得分:1)

错误是正确的。例如,您可以将T设为string & {x: number}来调用函数,这可能没有意义,但有可能。然后typeof条件将返回true,但是stringIdentity的结果将是string类型,而不是T

一种解决方案是转换您的标识函数,使其也具有通用性。另一个解决方案是仅添加类型转换,因为任何将string & {x: number}用作T的人都是不太可能的。

但是我想实际上是这样的:您简化了您的实际问题,以使其成为StackOverflow问题,但是您可能简化了太多,现在还不清楚您的实际设置是什么。您是否真的在对字符串和数字进行运算?

答案 1 :(得分:1)

您可以按照以下步骤实现:

    const identity = <T = string | number>(original: T): typeof original => {
        if (typeof original === 'string') {
            return stringIdentity(original) as typeof original;
        } 
        if (typeof original === 'number') {
            return numIdentity(original) as typeof original;
        }
    }

    const stringIdentity = (original: string): string => {
        return original
    }

    const numIdentity = (original: number): number => {
        return original
    }

Playground

  

警告:在您的身份函数中,如果我传递对象(字符串和数字都不传递)怎么办?如果将标识函数的返回类型标记为T,则必须处理所有可能的类型。您的身份函数会在给定类型的对象上返回void。