简体   繁体   English

Typescript“+”运算符如何与泛型和函数一起使用?

[英]How does Typescript "+" operator work with generics and functions?

I have a function that takes some value, and executes + operator over it and a 2 value:我有一个函数,它需要一些值,并在它上面执行+运算符和一个2值:

function myFunction(input: number): number {
    return input + 2;
}

If I pass a number, it will add this number to 2 :如果我传递一个数字,它会将这个数字添加到2

const result = myFunction(2);
console.log('Result: ', result);
// Result: 2

If I pass a string, it will concatenate this string to 2 :如果我传递一个字符串,它会将这个字符串连接到2

const result = myFunction('2');
console.log('Result: ', result);
// Result: "22"

Everything good so far.到目前为止一切都很好。 Now I want to use generics in order to capture the type:现在我想使用泛型来捕获类型:

function myFunction<T>(input: T): T {
    return input + 2;
}

And if I want to use it capturing the implicit type of the parameter I can do:如果我想使用它来捕获参数的隐式类型,我可以这样做:

const result = myFunction(2);
console.log('Result: ', result);
// Error: `(parameter) input: T. Operator '+' cannot be applied to types 'T' and '2'.`

As you see TypeScript returns an error about the type and the + operator, and I can't understand why.如您所见,TypeScript 返回有关类型和+运算符的错误,我不明白为什么。 The same if I set the type explicitly:如果我明确设置类型,则相同:

const result = myFunction<number>(2);
console.log('Result: ', result);
// Error: `(parameter) input: T. Operator '+' cannot be applied to types 'T' and '2'.`

I cant understand why it returns an error with + .我不明白为什么它会返回错误+ Any help will be welcome!欢迎任何帮助!

In general, TypeScript + operator is more restrictive than JavaScript + operator.一般来说,TypeScript +运算符比 JavaScript +运算符更严格。 Latter and can do implicit conversions between types and is more tolerant in terms of its operands.后者可以在类型之间进行隐式转换,并且在操作数方面更宽容。

Interaction with Generics and functions与泛型和函数的交互

Let's take your function example.让我们以你的函数为例。 Given myFunction down under, you get the error as T can be literally anything (see TypeScript + operator section down under for compatible types).鉴于下面的myFunction ,您会收到错误,因为T可以是任何字面意思(请参阅下面的 TypeScript + 运算符部分以了解兼容类型)。

function myFunction<T>(input: T): T {
  // Operator '+' cannot be applied to types 'T' and '2'.  
  return input + 2; 
}

TypeScript also requires, that you narrow down an union type like string | number TypeScript 还要求您缩小联合类型的范围,例如string | number string | number via control flow analysis. 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
}

Unfortunately, type narrowing does not work so well with generics extending a union type yet:不幸的是,类型缩小在扩展联合类型的泛型中效果不佳:

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;
  }
}

So that would be the final version and answer to your question, I guess.所以这将是最终版本并回答你的问题,我猜。 As enhancement, a neat thing is to actually return a conditional type.作为增强,一个整洁的事情是实际返回一个条件类型。 So when we put in string, we want string back.因此,当我们输入字符串时,我们想要返回字符串。 Analogues number -> number .模拟number -> number See this Playground example.请参阅此游乐场示例。


Possible combinations for TypeScript + operator TypeScript +运算符的可能组合

Type matrix for operands (empty spaces means compile error; eg between "Other" and "Boolean" type):操作数的类型矩阵(空格表示编译错误;例如在“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  |        |
+----------+---------+----------+---------+---------+--------+

Excerpt from the specs:规范摘录:

The binary + operator requires both operands to be of the Number primitive type or an enum type, or at least one of the operands to be of type Any or the String primitive type.二进制 + 运算符要求两个操作数都是 Number 基本类型或枚举类型,或者至少一个操作数是 Any 类型或 String 基本类型。 Operands of an enum type are treated as having the primitive type Number.枚举类型的操作数被视为具有基本类型 Number。 If one operand is the null or undefined value, it is treated as having the type of the other operand.如果一个操作数是空值或未定义值,则将其视为具有另一操作数的类型。 If both operands are of the Number primitive type, the result is of the Number primitive type.如果两个操作数都是 Number 原始类型,则结果是 Number 原始类型。 If one or both operands are of the String primitive type, the result is of the String primitive type.如果一个或两个操作数是 String 原始类型,则结果是 String 原始类型。 Otherwise, the result is of type Any.否则,结果为 Any 类型。

Some of the phrases seem a bit outdated.有些短语似乎有点过时了。 Numeric enums resolve to numbers, but string enums are treated as strings.数字枚举解析为数字,但字符串枚举被视为字符串。 With null or undefined and number you get a compile error regardless strict settings or not, with string you do a concatenation.使用nullundefined和 number 无论是否严格设置,都会出现编译错误,使用 string 进行连接。 Playground 操场


Background info: Javascript + operator背景信息: Javascript +运算符

The addition operator produces the sum of numeric operands or string concatenation.加法运算符产生数字操作数或字符串连接的总和。

Some constellations, you can only "do" in JavaScript:有些星座,你只能在 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

Playground 操场

Hope, this wasn't too much text for the scope of your question!希望,对于您的问题范围来说,这不是太多的文字!

Cheers干杯

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM