Typescript泛型与返回类型不兼容

Typescript泛型与返回类型不兼容,typescript,generics,typescript-typings,typescript-generics,Typescript,Generics,Typescript Typings,Typescript Generics,我在typescript泛型方面遇到了一个问题: 函数isString(a:any):a是字符串{ 返回a的类型==='string' } 函数concat(a:T,b:T):T{ if(i字符串(a)和&i字符串(b)){ 返回a.concat(b) } 返回a+b } 这是一个功能%20%20%26%26%26%26%26%26%26%20%26%20%26%20%26%20%20%20%7%7%7%7%C%20%20%20%C%20%20%20%20%7%20%7%20%20%20%20

我在typescript泛型方面遇到了一个问题:

函数isString(a:any):a是字符串{
返回a的类型==='string'
}
函数concat(a:T,b:T):T{
if(i字符串(a)和&i字符串(b)){
返回a.concat(b)
}
返回a+b
}
这是一个功能%20%20%26%26%26%26%26%26%26%20%26%20%26%20%26%20%20%20%7%7%7%7%C%20%20%20%C%20%20%20%20%7%20%7%20%20%20%20%20%20%20%20%20%20%26%26%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%是2B%20b%0D%0A%7D%0D%0A


打字似乎合适,但我有一些错误。关于typescript泛型似乎有一些困惑,但我找到的答案没有一个对基本用例有帮助。

typescript没有通过控制流缩小泛型类型(请参阅)。因此,即使已知
a
的类型为
string
T
的类型仍将顽固地保持
T
。使代码按原样编译的唯一方法是使用安抚编译器(如注释中所述):

现在,这些示例的行为将与您预期的一样:

const oops1 = concat("a", "b"); // string
const oops2 = concat(5, 6); // number
let notSure = Math.random() < 0.5 ? "a" : 1 
const oops3 = concat(notSure, 100); // error, notSure not allowed
const oops1=concat(“a”、“b”);//一串
常数oops2=concat(5,6);//数
让notSure=Math.random()<0.5?“a”:1
常量oops3=concat(不确定,100);//错误,不确定不允许
您可以使用泛型和,获得相同的行为,但这可能不值得:

type StringOrNumber<T extends string | number> =
    [T] extends [string] ? string :
    [T] extends [number] ? number : never

function concat<T extends string | number>(
    a: T,
    b: StringOrNumber<T>
): StringOrNumber<T> {
    if (isString(a) && isString(b)) {
        return a.concat(b) as any;
    }
    return (a as number) + (b as number) as any;
}

const oops1 = concat("a", "b"); // string
const oops2 = concat(5, 6); // number
let notSure = Math.random() < 0.5 ? "a" : 1
const oops3 = concat(notSure, 100); // error
输入StringOrNumber=
[T] 扩展[字符串]?字符串:
[T] 扩展[数字]?号码:从不
函数concat(
a:T,
b:StringOrNumber
):StringOrNumber{
if(i字符串(a)和&i字符串(b)){
返回a.concat(b)作为任何;
}
返回(a为数字)+(b为数字)如有;
}
常量oops1=concat(“a”、“b”);//一串
常数oops2=concat(5,6);//数
让notSure=Math.random()<0.5?“a”:1
常量oops3=concat(不确定,100);//错误

您缺少一个cast:
将a.concat(b)返回为T
。还有:
返回编号(a)+编号(b)作为T
function concat(a: string, b: string): string;
function concat(a: number, b: number): number;
function concat(a: string | number, b: string | number): string | number {
    if (isString(a) && isString(b)) {
        return a.concat(b);
    }
    return (a as number) + (b as number);
}
const oops1 = concat("a", "b"); // string
const oops2 = concat(5, 6); // number
let notSure = Math.random() < 0.5 ? "a" : 1 
const oops3 = concat(notSure, 100); // error, notSure not allowed
type StringOrNumber<T extends string | number> =
    [T] extends [string] ? string :
    [T] extends [number] ? number : never

function concat<T extends string | number>(
    a: T,
    b: StringOrNumber<T>
): StringOrNumber<T> {
    if (isString(a) && isString(b)) {
        return a.concat(b) as any;
    }
    return (a as number) + (b as number) as any;
}

const oops1 = concat("a", "b"); // string
const oops2 = concat(5, 6); // number
let notSure = Math.random() < 0.5 ? "a" : 1
const oops3 = concat(notSure, 100); // error