我有一个函数,该函数需要一些值,并对其执行+
运算符和一个2
值:
function myFunction(input: number): number {
return input + 2;
}
如果我输入一个数字,它将把这个数字添加到2
:
const result = myFunction(2);
console.log('Result: ', result);
// Result: 2
如果我传递一个字符串,它将把这个字符串连接到2
:
const result = myFunction(");
console.log('Result: ', result);
// Result: "22"
到目前为止一切都很好。现在,我想使用泛型来捕获类型:
function myFunction<T>(input: T): T {
return input + 2;
}
如果我要使用它来捕获参数的隐式类型,我可以这样做:
const result = myFunction(2);
console.log('Result: ', result);
// Error: `(parameter) input: T. Operator '+' cannot be applied to types 'T' and '2'.`
如您所见,TypeScript返回有关类型和+
运算符的错误,我不明白为什么。如果我明确设置类型也是如此:
const result = myFunction<number>(2);
console.log('Result: ', result);
// Error: `(parameter) input: T. Operator '+' cannot be applied to types 'T' and '2'.`
我无法理解为什么它返回+
的错误。任何帮助都将受到欢迎!
答案 0 :(得分:4)
通常,TypeScript +
运算符比JavaScript +
运算符更具限制性。后者可以在类型之间进行隐式转换,并且在操作数方面更宽容。
让我们以您的函数为例。给定myFunction
下方的位置,就会出现错误,因为T
可以是任何文字(有关兼容类型,请参见下方的TypeScript +运算符部分)。
function myFunction<T>(input: T): T {
// Operator '+' cannot be applied to types 'T' and '2'.
return input + 2;
}
TypeScript还要求您通过控制流分析来缩小诸如string | number
之类的联合类型。
declare const t: string | number;
t + 3; // Operator '+' cannot be applied to types 'string | number' and '3'.
// this works!
if (typeof t === "string") {
const res = t + 3; // const res: string
} else {
const res = t + 3; // const res: number
}
不幸的是,generics extending a union type的类型变窄还不能很好地发挥作用:
function myFunction<T extends string | number>(input: T): string | number {
if (typeof input === "string") {
return input + 3;
} else {
// TypeScript could not narrow here to number, we have to cast.
const inputNumber = input as number;
return inputNumber + 3;
}
}
我想这将是最终版本并回答您的问题。作为增强,一个整洁的事情是实际上返回一个条件类型。因此,当我们输入字符串时,我们希望返回字符串。类似物number -> number
。请参见此Playground示例。
+
operator的可能组合操作数的类型矩阵(空格表示编译错误;例如,在“其他”和“布尔”类型之间):
+----------+---------+----------+---------+---------+--------+
| | Any | Boolean | Number | String | Other |
+----------+---------+----------+---------+---------+--------+
| Any | Any | Any | Any | String | Any |
| Boolean | Any | | | String | |
| Number | Any | | Number | String | |
| String | String | String | String | String | String |
| Other | Any | | | String | |
+----------+---------+----------+---------+---------+--------+
摘录自规格:
binary +运算符要求两个操作数均为Number原语类型或枚举类型,或至少一个操作数为Any类型或String原语类型。枚举类型的操作数被视为具有基本类型Number。如果一个操作数为空值或未定义值,则将其视为具有另一种操作数的类型。如果两个操作数均为Number原语类型,则结果为Number原语类型。如果一个或两个操作数均为String原语类型,则结果为String原语类型。否则,结果的类型为Any。
有些短语似乎有些过时了。数字枚举解析为数字,但字符串枚举被视为字符串。使用null
或undefined
和数字,无论是否进行严格的设置,都会出现编译错误,使用字符串进行串联。
Playground
+
operator 加法运算符产生数字操作数或字符串连接的总和。
某些星座,您只能在JavaScript中“执行”:
true + 1 // 2
false + false // 0
1 + undefined // NaN
1 + null // 1; typeof(1+ null) === "number"; // :)
new Date() + new Date() // toString() is invoked for both Date objects implicitly
希望,对于您的问题范围,这不是太多的文字!
欢呼