【问题标题】:Is there a way in TypeScript to warn about "1" + 1 = "11"? [duplicate]TypeScript 中有没有办法警告“1”+1 =“11”? [复制]
【发布时间】:2019-12-13 09:36:24
【问题描述】:

JavaScript 充满了像这样的警告:

const arr = [1, 2, 3]

for (const i in arr) {
  console.log(i + 1)
}

没有经验的 JS 开发者期望的结果是1 2 3,但实际上是01 11 21


看起来 TypeScript 默认没有警告连接字符串和数字,有没有办法做到这一点?

更准确地说:我如何才能收到有关 '1' + 1 等案例的警告

【问题讨论】:

  • 您的意思是除了将添加内容包装在一个函数中吗?无论如何,您会认为至少编译器会警告您在数组上使用for...in...
  • 我的意思是总是,独立于一个地方,例如在这种最简单的情况下:console.log('1' + 1)
  • "" + 1 在 JS 中是允许的,所以它在 TS 中是允许的。 console.log() 接受字符串和数字,所以这里没有错误。但是,如果您尝试将 i + 1 视为数字,则会收到错误消息。
  • 不可能,这是proposed and declinedeslinttslint 是您唯一的选择。
  • @AaronBeall 比这更微妙...诸如“X 在 JS 中允许,因此在 TS 中允许”之类的语句通常是 misleading or untrue。问题是 JS 中的用法是否更可能是错误而不是有效代码?在这种情况下,很多真实世界的 JS 代码使用了像 console.log("There are " + files.length + " files") 这样的结构,以至于 TS 的维护者认为这里不值得更严格。

标签: javascript typescript concatenation eslint typescript-eslint


【解决方案1】:

TS Lint 可以防止不当使用for..inhttps://palantir.github.io/tslint/rules/forin/

【讨论】:

  • 谢谢,但我问的不仅仅是for..in,还有一般情况,例如'1' + 1
  • 另外,tslint 一直是 deprecated,我不想使用已弃用的 linter。
【解决方案2】:

更新的有效答案 使用@typescript-eslint/restrict-plus-operands 规则。两个操作数都必须是字符串或数字,但不能同时是两者:

来自https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#usage的eslint配置

{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "project": "./tsconfig.json"
  },
  "plugins": ["@typescript-eslint"],
  "rules": {
    "@typescript-eslint/restrict-plus-operands": "error"
  }
}

原创

TS Lint 有“首选模板”规则,尽管我没有在这种情况下尝试过。它应该可以工作,因为 TypeScript 将 i 变量视为字符串类型。

https://palantir.github.io/tslint/rules/prefer-template/

此规则将要求您执行以下操作以使串联工作:

console.log(`${i}1`);

这至少应该向开发人员发出他们正在尝试执行连接的信号。

仅供参考,TS Lint 已被弃用,取而代之的是 ES Lint,尽管我还没有将我的任何项目转移到该工具上。

更新 ES Lint 也有同样的规则:https://eslint.org/docs/rules/prefer-template

【讨论】:

  • 谢谢@ps2goat。虽然prefer-template 有助于处理console.log('1' + 1) 之类的情况,但它还不够“聪明”,无法处理const a = '1'; console.log(a + 1) 之类的更复杂的情况
  • 你是对的。我现在也很失望:(
  • @LimonMonte - 使用我在我的机器上测试过的新规则进行了更新。
  • 谢谢@ps2goat,这正是我想要的!我更新了您的答案以复制粘贴 Friednly eslint 配置。谢谢伙计,现在我的项目不会出现意外结果!
【解决方案3】:

您连接的是数组属性名称,而不是它的值。这是因为for...in 迭代对象的属性。我认为你想要做的是:

const arr = [1, 2, 3]

for (const i in arr) {
  console.log(arr[i] + 1)
}

您总是可以在其中编写一些代码来验证输入的类型,但首先了解for...in 循环很重要——这里有一些documentation regarding for...in use with arrays

您可以使用typeof 在您的函数中进行简单的类型检查:

function doConcat(operand1, operand2) {
  if (typeof operand1 !== typeof operand2) { //simple typeof check
    console.log(`Cannot concat type: ${typeof operand1} with type: ${typeof operand2}`);
    return;
  }
  return operand1 + operand2;
}

const arr1 = [1, 2, 3]; //Should work - adding 2 numbers
for (const i in arr1) {
  console.log(doConcat(arr1[i], 1));
}

const arr2 = ['a', 'b', 'c']; //Should bomb - trying to concat number and string
for (const j in arr2) {
  doConcat(arr2[j], 1);
}

【讨论】:

  • 我相信我没有正确地提出这个问题,这与for...in 的工作方式无关,而是关于数字和字符串的连接。数字和字符串的连接可能会导致一些意想不到的结果,我想避免这种情况。
  • 明白了...我会更新我的答案以反映这一点
猜你喜欢
  • 2010-09-16
  • 2020-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-10
  • 1970-01-01
  • 2010-12-14
相关资源
最近更新 更多