[英]How does Typescript "+" operator work with generics and functions?
我有一个函数,它需要一些值,并在它上面执行+
运算符和一个2
值:
function myFunction(input: number): number {
return input + 2;
}
如果我传递一个数字,它会将这个数字添加到2
:
const result = myFunction(2);
console.log('Result: ', result);
// Result: 2
如果我传递一个字符串,它会将这个字符串连接到2
:
const result = myFunction('2');
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'.`
我不明白为什么它会返回错误+
。 欢迎任何帮助!
一般来说,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
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
}
不幸的是,类型缩小在扩展联合类型的泛型中效果不佳:
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
。 请参阅此游乐场示例。
+
运算符的可能组合操作数的类型矩阵(空格表示编译错误;例如在“Other”和“Boolean”类型之间):
+----------+---------+----------+---------+---------+--------+
| | 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 | |
+----------+---------+----------+---------+---------+--------+
规范摘录:
二进制 + 运算符要求两个操作数都是 Number 基本类型或枚举类型,或者至少一个操作数是 Any 类型或 String 基本类型。 枚举类型的操作数被视为具有基本类型 Number。 如果一个操作数是空值或未定义值,则将其视为具有另一操作数的类型。 如果两个操作数都是 Number 原始类型,则结果是 Number 原始类型。 如果一个或两个操作数是 String 原始类型,则结果是 String 原始类型。 否则,结果为 Any 类型。
有些短语似乎有点过时了。 数字枚举解析为数字,但字符串枚举被视为字符串。 使用null
或undefined
和 number 无论是否严格设置,都会出现编译错误,使用 string 进行连接。 操场
+
运算符加法运算符产生数字操作数或字符串连接的总和。
有些星座,你只能在 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
希望,对于您的问题范围来说,这不是太多的文字!
干杯
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.