diff --git a/README.md b/README.md index 9d4efae..f3b07d0 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ > Simplified Chinese website -The synchronization frequency is the same as the ESLint release frequency (the last sync was [v8.48.0](https://github.com/eslint/eslint/tree/v8.48.0)) +The synchronization frequency is the same as the ESLint release frequency (the last sync was [v8.49.0](https://github.com/eslint/eslint/tree/v8.49.0)) ## Contribute diff --git a/src/extend/code-path-analysis.md b/src/extend/code-path-analysis.md index 19bb86b..13bef10 100644 --- a/src/extend/code-path-analysis.md +++ b/src/extend/code-path-analysis.md @@ -1,6 +1,5 @@ --- title: 代码链路分析详情 - --- ESLint 规则可以使用代码链路。 @@ -59,74 +58,107 @@ bar(); 有五个与代码链路有关的事件,你可以在规则中定义事件处理程序。 ```js -module.exports = function(context) { - return { - /** - * 这在分析代码链路的开始阶段被调用。 - * 此时代码链路对象只有初始段。 - * - * @param {CodePath} codePath - 新的代码链路 - * @param {ASTNode} node - 当前节点 - * @returns {void} - */ - "onCodePathStart": function(codePath, node) { - // 对 codePath 做点什么 - }, - - /** - * 这是在分析代码链路结束时调用的。 - * 在这个时候,代码链路对象已经完成。 - * - * @param {CodePath} codePath - 完成的代码路径 - * @param {ASTNode} node - 当前节点 - * @returns {void} - */ - "onCodePathEnd": function(codePath, node) { - // 对 codePath 做点什么 - }, - - /** - * 当创建代码链路段时,会调用它。 - * 这意味着代码链路被分叉或合并了。 - * 在这个时候,该段有以前的段,并且已经被 - * 判断为可达或不可达。 - * - * @param {CodePathSegment} segment - 新的代码链路段 - * @param {ASTNode} node - 当前节点 - * @returns {void} - */ - "onCodePathSegmentStart": function(segment, node) { - // 做点什么 - }, - - /** - *当一个代码链路段被留下时,这被调用。 - *在这个时候,该段还没有下一个段。 - * - * @param {CodePathSegment} segment - 左边的代码链路段 - * @param {ASTNode} node - 当前节点 - * @returns {void} - */ - "onCodePathSegmentEnd": function(segment, node) { - // 做点什么 - }, - - /** - * 当代码链路段被循环使用时,会调用它。 - * 通常情况下,段在创建时有每一个前段。 - * 但当循环时,一个段被作为一个新的前段添加到一个 - * 现有的段。 - * - * @param {CodePathSegment} fromSegment - 代码链路段的源码 - * @param {CodePathSegment} toSegment - 目标代码链路段 - * @param {ASTNode} node - 当前节点 - * @returns {void} - */ - "onCodePathSegmentLoop": function(fromSegment, toSegment, node) { - // 做点什么 - } - }; -}; +module.exports = { + meta: { + // ... + }, + create(context) { + + return { + /** + * This is called at the start of analyzing a code path. + * In this time, the code path object has only the initial segment. + * + * @param {CodePath} codePath - The new code path. + * @param {ASTNode} node - The current node. + * @returns {void} + */ + onCodePathStart(codePath, node) { + // do something with codePath + }, + + /** + * This is called at the end of analyzing a code path. + * In this time, the code path object is complete. + * + * @param {CodePath} codePath - The completed code path. + * @param {ASTNode} node - The current node. + * @returns {void} + */ + onCodePathEnd(codePath, node) { + // do something with codePath + }, + + /** + * This is called when a reachable code path segment was created. + * It meant the code path is forked or merged. + * In this time, the segment has the previous segments and has been + * judged reachable or not. + * + * @param {CodePathSegment} segment - The new code path segment. + * @param {ASTNode} node - The current node. + * @returns {void} + */ + onCodePathSegmentStart(segment, node) { + // do something with segment + }, + + /** + * This is called when a reachable code path segment was left. + * In this time, the segment does not have the next segments yet. + * + * @param {CodePathSegment} segment - The left code path segment. + * @param {ASTNode} node - The current node. + * @returns {void} + */ + onCodePathSegmentEnd(segment, node) { + // do something with segment + }, + + /** + * This is called when an unreachable code path segment was created. + * It meant the code path is forked or merged. + * In this time, the segment has the previous segments and has been + * judged reachable or not. + * + * @param {CodePathSegment} segment - The new code path segment. + * @param {ASTNode} node - The current node. + * @returns {void} + */ + onUnreachableCodePathSegmentStart(segment, node) { + // do something with segment + }, + + /** + * This is called when an unreachable code path segment was left. + * In this time, the segment does not have the next segments yet. + * + * @param {CodePathSegment} segment - The left code path segment. + * @param {ASTNode} node - The current node. + * @returns {void} + */ + onUnreachableCodePathSegmentEnd(segment, node) { + // do something with segment + }, + + /** + * This is called when a code path segment was looped. + * Usually segments have each previous segments when created, + * but when looped, a segment is added as a new previous segment into a + * existing segment. + * + * @param {CodePathSegment} fromSegment - A code path segment of source. + * @param {CodePathSegment} toSegment - A code path segment of destination. + * @param {ASTNode} node - The current node. + * @returns {void} + */ + onCodePathSegmentLoop(fromSegment, toSegment, node) { + // do something with segment + } + }; + + } +} ``` ### 关于 `onCodePathSegmentLoop` @@ -146,7 +178,7 @@ bar(); 1. 首先,分析推进到循环的终点。 :::img-container - ![循环事件示例 1](./assets/images/code-path-analysis/loop-event-example-while-1.svg) + ![循环事件示例 1](../assets/images/code-path-analysis/loop-event-example-while-1.svg) ::: 1. 其次,它创建了循环链路。 @@ -212,35 +244,134 @@ bar(); ## 使用示例 -### 检查能否执行 +### 跟踪当前代码段位置 + +要跟踪当前代码路径段的位置,你可以定义一个规则,如下所示: ```js -function isReachable(segment) { - return segment.reachable; -} +module.exports = { + meta: { + // ... + }, + create(context) { + + // tracks the code path we are currently in + let currentCodePath; + + // tracks the segments we've traversed in the current code path + let currentSegments; + + // tracks all current segments for all open paths + const allCurrentSegments = []; + + return { + + onCodePathStart(codePath) { + currentCodePath = codePath; + allCurrentSegments.push(currentSegments); + currentSegments = new Set(); + }, + + onCodePathEnd(codePath) { + currentCodePath = codePath.upper; + currentSegments = allCurrentSegments.pop(); + }, + + onCodePathSegmentStart(segment) { + currentSegments.add(segment); + }, -module.exports = function(context) { - var codePathStack = []; - - return { - // 存储 CodePath 对象 - "onCodePathStart": function(codePath) { - codePathStack.push(codePath); - }, - "onCodePathEnd": function(codePath) { - codePathStack.pop(); - }, - - // 检查能否执行 - "ExpressionStatement": function(node) { - var codePath = codePathStack[codePathStack.length - 1]; - - // 检查当前的代码链路段 - if (!codePath.currentSegments.some(isReachable)) { - context.report({message: "Unreachable!", node: node}); + onCodePathSegmentEnd(segment) { + currentSegments.delete(segment); + }, + + onUnreachableCodePathSegmentStart(segment) { + currentSegments.add(segment); + }, + + onUnreachableCodePathSegmentEnd(segment) { + currentSegments.delete(segment); } + }; + + } +}; +``` + +在这个例子中,`currentCodePath` 变量用于访问当前正在遍历的代码路径,而 `currentSegments` 变量则跟踪到目前为止已经遍历的该代码路径中的段。请注意,`currentSegments` 既开始时为空集,也在遍历进行时不断更新。 + +跟踪当前代码路径段的位置有助于分析导致特定节点的代码路径,就像在下一个例子中所示。 + +### 寻找不可达的节点 + +要找到不可达的节点,跟踪当前代码路径段的位置,然后使用节点访问器检查是否有任何可达的段。例如,以下代码查找任何不可达的 `ExpressionStatement`。 + +```js +function areAnySegmentsReachable(segments) { + for (const segment of segments) { + if (segment.reachable) { + return true; } - }; + } + + return false; +} + +module.exports = { + meta: { + // ... + }, + create(context) { + + // tracks the code path we are currently in + let currentCodePath; + + // tracks the segments we've traversed in the current code path + let currentSegments; + + // tracks all current segments for all open paths + const allCurrentSegments = []; + + return { + + onCodePathStart(codePath) { + currentCodePath = codePath; + allCurrentSegments.push(currentSegments); + currentSegments = new Set(); + }, + + onCodePathEnd(codePath) { + currentCodePath = codePath.upper; + currentSegments = allCurrentSegments.pop(); + }, + + onCodePathSegmentStart(segment) { + currentSegments.add(segment); + }, + + onCodePathSegmentEnd(segment) { + currentSegments.delete(segment); + }, + + onUnreachableCodePathSegmentStart(segment) { + currentSegments.add(segment); + }, + + onUnreachableCodePathSegmentEnd(segment) { + currentSegments.delete(segment); + }, + + ExpressionStatement(node) { + + // check all the code path segments that led to this node + if (!areAnySegmentsReachable(currentSegments)) { + context.report({ message: "Unreachable!", node }); + } + } + + }; + + } }; ``` @@ -249,7 +380,7 @@ module.exports = function(context) { [no-fallthrough](https://github.com/eslint/eslint/blob/HEAD/lib/rules/no-fallthrough.js), [consistent-return](https://github.com/eslint/eslint/blob/HEAD/lib/rules/consistent-return.js) -### 要想检查代码链路状态 +### 检查是否每个路径都调用了函数 此示例检查每个链路中是否调用了 `cb` 参数。 `CodePath` 和 `CodePathSegment` 的实例被共享给每个规则。 @@ -271,75 +402,101 @@ function isCbCalled(info) { return info.cbCalled; } -module.exports = function(context) { - var funcInfoStack = []; - var segmentInfoMap = Object.create(null); - - return { - // 检查 `cb`. - "onCodePathStart": function(codePath, node) { - funcInfoStack.push({ - codePath: codePath, - hasCb: hasCb(node, context) - }); - }, - "onCodePathEnd": function(codePath, node) { - funcInfoStack.pop(); - - // 检查每个链路是否调用了 `cb` - var cbCalled = codePath.finalSegments.every(function(segment) { - var info = segmentInfoMap[segment.id]; - return info.cbCalled; - }); - - if (!cbCalled) { - context.report({ - message: "`cb` should be called in every path.", - node: node +module.exports = { + meta: { + // ... + }, + create(context) { + + let funcInfo; + const funcInfoStack = []; + const segmentInfoMap = Object.create(null); + + return { + // Checks `cb`. + onCodePathStart(codePath, node) { + funcInfoStack.push(funcInfo); + + funcInfo = { + codePath: codePath, + hasCb: hasCb(node, context), + currentSegments: new Set() + }; + }, + + onCodePathEnd(codePath, node) { + funcInfo = funcInfoStack.pop(); + + // Checks `cb` was called in every paths. + const cbCalled = codePath.finalSegments.every(function(segment) { + const info = segmentInfoMap[segment.id]; + return info.cbCalled; }); - } - }, - - // 管理代码链路状态 - "onCodePathSegmentStart": function(segment) { - var funcInfo = funcInfoStack[funcInfoStack.length - 1]; - // 如果不存在 `cb`,则忽略。 - if (!funcInfo.hasCb) { - return; + if (!cbCalled) { + context.report({ + message: "`cb` should be called in every path.", + node: node + }); + } + }, + + // Manages state of code paths and tracks traversed segments + onCodePathSegmentStart(segment) { + + funcInfo.currentSegments.add(segment); + + // Ignores if `cb` doesn't exist. + if (!funcInfo.hasCb) { + return; + } + + // Initialize state of this path. + const info = segmentInfoMap[segment.id] = { + cbCalled: false + }; + + // If there are the previous paths, merges state. + // Checks `cb` was called in every previous path. + if (segment.prevSegments.length > 0) { + info.cbCalled = segment.prevSegments.every(isCbCalled); + } + }, + + // Tracks unreachable segment traversal + onUnreachableCodePathSegmentStart(segment) { + funcInfo.currentSegments.add(segment); + }, + + // Tracks reachable segment traversal + onCodePathSegmentEnd(segment) { + funcInfo.currentSegments.delete(segment); + }, + + // Tracks unreachable segment traversal + onUnreachableCodePathSegmentEnd(segment) { + funcInfo.currentSegments.delete(segment); + }, + + // Checks reachable or not. + CallExpression(node) { + + // Ignores if `cb` doesn't exist. + if (!funcInfo.hasCb) { + return; + } + + // Sets marks that `cb` was called. + const callee = node.callee; + if (callee.type === "Identifier" && callee.name === "cb") { + funcInfo.currentSegments.forEach(segment => { + const info = segmentInfoMap[segment.id]; + info.cbCalled = true; + }); + } } - - // 初始化这个链路的状态。 - var info = segmentInfoMap[segment.id] = { - cbCalled: false - }; - - // 如果有以前的链路,则合并状态 - // 检查每个此前的链路是否调用了 `cb` - if (segment.prevSegments.length > 0) { - info.cbCalled = segment.prevSegments.every(isCbCalled); - } - }, - - // 检查是否可达 - "CallExpression": function(node) { - var funcInfo = funcInfoStack[funcInfoStack.length - 1]; - - // 如果不存在 `cb`,则忽略 - if (!funcInfo.hasCb) { - return; - } - - // 设置调用 `cb` 的标记。 - var callee = node.callee; - if (callee.type === "Identifier" && callee.name === "cb") { - funcInfo.codePath.currentSegments.forEach(function(segment) { - var info = segmentInfoMap[segment.id]; - info.cbCalled = true; - }); - } - } - }; + }; + } }; ``` diff --git a/src/rules/lines-between-class-members.md b/src/rules/lines-between-class-members.md index 62e18a4..de5755e 100644 --- a/src/rules/lines-between-class-members.md +++ b/src/rules/lines-between-class-members.md @@ -67,16 +67,21 @@ class MyClass { ### 选项 -这个规则有一个字符串选项和一个对象选项。 +这个规则有两个选项,第一个选项可以是字符串或对象,第二个选项是一个对象。 -字符串选项: +第一个选项可以是字符串 `"always"` 或 `"never"`,或者一个拥有名为 `enforce` 属性的对象: -* `"always"`(默认)要求在类成员后有一个空行。 -* `"never"` 不允许在类成员后出现空行。 +* `"always"`(默认)要求在类成员后面有一个空行。 +* `"never"` 不允许在类成员后面有空行。 +* `Object`:拥有名为 `enforce` 属性的对象。`enforce` 属性应该是一个对象数组,每个对象都指定了在特定类成员对之间强制使用空行的配置。 + * **enforce**:你可以提供任意数量的配置。如果成员对匹配多个配置,将使用最后匹配的配置。如果成员对不回匹配任何配置,而回被忽略。每个对象应该具有以下属性: + * **blankLine**:可以设置为 `"always"` 或 `"never"`,表示是否需要在指定的成员之间要求或禁止空行。 + * **prev**:指定前一个类成员的类型。它可以是 `"method"` 表示类方法,`"field"` 表示类字段,或 `"*"` 表示任何类成员。 + * **next**:指定后一个类成员的类型。它遵循与 `prev` 相同的选项。 -对象选项: +第二个选项是拥有名为 `exceptAfterSingleLine` 属性的对象: -* `"exceptAfterSingleLine": false`(默认)**不**跳过检查单行类成员后的空行。 +* `"exceptAfterSingleLine": false`(默认)**不回**跳过检查单行类成员后的空行。 * `"exceptAfterSingleLine": true` 跳过检查单行类成员后的空行。 使用此规则与字符串选项的**错误**示例: @@ -127,6 +132,146 @@ class Foo{ ::: +使用此规则与具有配置数组选项的**错误**示例: + +::: incorrect + +```js +// disallows blank lines between methods +/*eslint lines-between-class-members: [ + "error", + { + enforce: [ + { blankLine: "never", prev: "method", next: "method" } + ] + }, +]*/ + +class MyClass { + constructor(height, width) { + this.height = height; + this.width = width; + } + + fieldA = 'Field A'; + #fieldB = 'Field B'; + + method1() {} + + get area() { + return this.method1(); + } + + method2() {} +} +``` + +::: + +::: incorrect + +```js +// requires blank lines around fields, disallows blank lines between methods +/*eslint lines-between-class-members: [ + "error", + { + enforce: [ + { blankLine: "always", prev: "*", next: "field" }, + { blankLine: "always", prev: "field", next: "*" }, + { blankLine: "never", prev: "method", next: "method" } + ] + }, +]*/ + +class MyClass { + constructor(height, width) { + this.height = height; + this.width = width; + } + fieldA = 'Field A'; + #fieldB = 'Field B'; + method1() {} + + get area() { + return this.method1(); + } + + method2() {} +} +``` + +::: + +使用此规则与具有配置数组选项的**正确**示例: + +::: correct + +```js +// disallows blank lines between methods +/*eslint lines-between-class-members: [ + "error", + { + enforce: [ + { blankLine: "never", prev: "method", next: "method" } + ] + }, +]*/ + +class MyClass { + constructor(height, width) { + this.height = height; + this.width = width; + } + + fieldA = 'Field A'; + + #fieldB = 'Field B'; + + method1() {} + get area() { + return this.method1(); + } + method2() {} +} +``` + +::: + +::: correct + +```js +// requires blank lines around fields, disallows blank lines between methods +/*eslint lines-between-class-members: [ + "error", + { + enforce: [ + { blankLine: "always", prev: "*", next: "field" }, + { blankLine: "always", prev: "field", next: "*" }, + { blankLine: "never", prev: "method", next: "method" } + ] + }, +]*/ + +class MyClass { + constructor(height, width) { + this.height = height; + this.width = width; + } + + fieldA = 'Field A'; + + #fieldB = 'Field B'; + + method1() {} + get area() { + return this.method1(); + } + method2() {} +} +``` + +::: + 使用此规则与对象选项的**正确**示例: ::: correct @@ -146,6 +291,40 @@ class Foo{ ::: +::: correct + +```js +/*eslint lines-between-class-members: [ + "error", + { + enforce: [ + { blankLine: "always", prev: "*", next: "method" }, + { blankLine: "always", prev: "method", next: "*" }, + { blankLine: "always", prev: "field", next: "field" } + ] + }, + { exceptAfterSingleLine: true } +]*/ + +class MyClass { + constructor(height, width) { + this.height = height; + this.width = width; + } + + fieldA = 'Field A'; + #fieldB = 'Field B'; + method1() {} + get area() { + return this.method1(); + } + + method2() {} +} +``` + +::: + ## 何时不用 如果你不想类成员之间有空行,你可以禁用这个规则。 diff --git a/src/rules/no-const-assign.md b/src/rules/no-const-assign.md index 9145a0d..63b1f3c 100644 --- a/src/rules/no-const-assign.md +++ b/src/rules/no-const-assign.md @@ -1,6 +1,7 @@ --- title: no-const-assign rule_type: problem +handled_by_typescript: true --- 我们不能修改使用 `const` 关键字声明的变量。 diff --git a/src/rules/no-dupe-args.md b/src/rules/no-dupe-args.md index a1459a5..cad027e 100644 --- a/src/rules/no-dupe-args.md +++ b/src/rules/no-dupe-args.md @@ -1,6 +1,7 @@ --- title: no-dupe-args rule_type: problem +handled_by_typescript: true --- 如果在一个函数定义中,有一个以上的参数有相同的名称,那么最后出现的参数会“影射”前面的参数。重复的名称可能是笔误。 diff --git a/src/rules/no-dupe-class-members.md b/src/rules/no-dupe-class-members.md index dfa2a52..938c674 100644 --- a/src/rules/no-dupe-class-members.md +++ b/src/rules/no-dupe-class-members.md @@ -1,6 +1,7 @@ --- title: no-dupe-class-members rule_type: problem +handled_by_typescript: true --- 如果在类成员中存在同名的声明,最后一个声明会无声地覆盖其他声明。 @@ -99,5 +100,3 @@ class Foo { 不应该在 ES3/5 环境中使用此规则。 在 ES2015(ES6)或更高版本中,如果你不想被通知类成员中的重复名称,你可以安全地禁用这个规则。 - -在使用 TypeScript 时,也可以安全地禁用此规则,因为 TypeScript 编译器已经检查过重复的函数实现。 diff --git a/src/rules/no-dupe-keys.md b/src/rules/no-dupe-keys.md index 47fdea2..4f21013 100644 --- a/src/rules/no-dupe-keys.md +++ b/src/rules/no-dupe-keys.md @@ -1,6 +1,7 @@ --- title: no-dupe-keys rule_type: problem +handled_by_typescript: true --- 在对象字面中具有相同键的多个属性会在你的应用程序中引起意外的行为。 diff --git a/src/rules/no-func-assign.md b/src/rules/no-func-assign.md index d98d003..f8ad110 100644 --- a/src/rules/no-func-assign.md +++ b/src/rules/no-func-assign.md @@ -1,6 +1,7 @@ --- title: no-func-assign rule_type: problem +handled_by_typescript: true --- JavaScript 函数可以被写成 FunctionDeclaration `function foo() { ... }` 或 FunctionExpression `var foo = function() { ... };`. 虽然 JavaScript 解释器可能会容忍它,但覆盖/重新分配一个写成 FunctionDeclaration 的函数,往往表明有错误或问题。 diff --git a/src/rules/no-import-assign.md b/src/rules/no-import-assign.md index 7c5a199..81a11d0 100644 --- a/src/rules/no-import-assign.md +++ b/src/rules/no-import-assign.md @@ -1,6 +1,8 @@ --- title: no-import-assign rule_type: problem +handled_by_typescript: true +extra_typescript_info: 注意编译器不会捕获 `Object.assign()` 的情况。因此,如果你在代码库中使用 `Object.assign()`,这个规则仍然会提供一些价值。 --- ES 模块对导入的绑定的更新会导致运行时错误。 diff --git a/src/rules/no-invalid-this.md b/src/rules/no-invalid-this.md index ece19f1..6ca7714 100644 --- a/src/rules/no-invalid-this.md +++ b/src/rules/no-invalid-this.md @@ -1,6 +1,8 @@ --- title: no-invalid-this rule_type: suggestion +handled_by_typescript: true +extra_typescript_info: 注意从技术上讲 TypeScript 只会在启用了 `strict` 或 `noImplicitThis` 标志时才会捕获这种情况。大多数 TypeScript 项目都启用了这些标志,因为它被认为是最佳实践。 --- 在严格模式下,类或类状对象之外的 `this` 关键字可能是 `undefined`,并引发 `TypeError`。 diff --git a/src/rules/no-new-symbol.md b/src/rules/no-new-symbol.md index 58efbe6..6bd772c 100644 --- a/src/rules/no-new-symbol.md +++ b/src/rules/no-new-symbol.md @@ -1,6 +1,7 @@ --- title: no-new-symbol rule_type: problem +handled_by_typescript: true further_reading: - https://www.ecma-international.org/ecma-262/6.0/#sec-symbol-objects --- diff --git a/src/rules/no-obj-calls.md b/src/rules/no-obj-calls.md index 97941c2..69f8f01 100644 --- a/src/rules/no-obj-calls.md +++ b/src/rules/no-obj-calls.md @@ -1,6 +1,7 @@ --- title: no-obj-calls rule_type: problem +handled_by_typescript: true further_reading: - https://es5.github.io/#x15.8 --- diff --git a/src/rules/no-promise-executor-return.md b/src/rules/no-promise-executor-return.md index 5616d27..83ed644 100644 --- a/src/rules/no-promise-executor-return.md +++ b/src/rules/no-promise-executor-return.md @@ -37,6 +37,7 @@ const myPromise = new Promise(function executor(resolve, reject) { ```js /*eslint no-promise-executor-return: "error"*/ +/*eslint-env es6*/ new Promise((resolve, reject) => { if (someCondition) { @@ -72,6 +73,7 @@ new Promise(() => { ```js /*eslint no-promise-executor-return: "error"*/ +/*eslint-env es6*/ new Promise((resolve, reject) => { if (someCondition) { @@ -101,3 +103,44 @@ Promise.resolve(1); ``` ::: + +## 选项 + +此规则接受选项,一个带有以下属性的对象: + +* `allowVoid`:如果设置为 `true`(默认为 `false`),此规则将允许返回 `void` 值。 + +### allowVoid + +使用此规则与 `{ "allowVoid": true }` 选项的**正确**示例: + +::: correct + +```js +/*eslint no-promise-executor-return: ["error", { allowVoid: true }]*/ +/*eslint-env es6*/ + +new Promise((resolve, reject) => { + if (someCondition) { + return void resolve(defaultResult); + } + getSomething((err, result) => { + if (err) { + reject(err); + } else { + resolve(result); + } + }); +}); + +new Promise((resolve, reject) => void getSomething((err, data) => { + if (err) { + reject(err); + } else { + resolve(data); + } +})); +new Promise(r => void r(1)); +``` + +::: diff --git a/src/rules/no-redeclare.md b/src/rules/no-redeclare.md index 3c6fd33..ce41c11 100644 --- a/src/rules/no-redeclare.md +++ b/src/rules/no-redeclare.md @@ -1,6 +1,8 @@ --- title: no-redeclare rule_type: suggestion +handled_by_typescript: true +extra_typescript_info: 注意尽管 TypeScript 会捕获 `let` 和 `const` 的重新声明,但不会捕获 `var` 的重新声明。因此,如果你在 TypeScript 代码库中使用传统的 `var` 关键字,这个规则仍然会提供一些价值。 related_rules: - no-shadow --- diff --git a/src/rules/no-setter-return.md b/src/rules/no-setter-return.md index 51d8dcf..37e564a 100644 --- a/src/rules/no-setter-return.md +++ b/src/rules/no-setter-return.md @@ -1,6 +1,7 @@ --- title: no-setter-return rule_type: problem +handled_by_typescript: true related_rules: - getter-return further_reading: diff --git a/src/rules/no-this-before-super.md b/src/rules/no-this-before-super.md index caf82af..51f7a00 100644 --- a/src/rules/no-this-before-super.md +++ b/src/rules/no-this-before-super.md @@ -1,6 +1,7 @@ --- title: no-this-before-super rule_type: problem +handled_by_typescript: true --- 在派生类的构造函数中,如果 `this`/`super` 在 `super()` 调用之前被使用,会引发引用错误。 diff --git a/src/rules/no-undef.md b/src/rules/no-undef.md index 345bc41..ec2a561 100644 --- a/src/rules/no-undef.md +++ b/src/rules/no-undef.md @@ -1,6 +1,7 @@ --- title: no-undef rule_type: problem +handled_by_typescript: true related_rules: - no-global-assign - no-redeclare diff --git a/src/rules/no-unreachable.md b/src/rules/no-unreachable.md index c30325f..4c1f259 100644 --- a/src/rules/no-unreachable.md +++ b/src/rules/no-unreachable.md @@ -1,6 +1,7 @@ --- title: no-unreachable rule_type: problem +handled_by_typescript: true --- 因为 `return`、`throw`、`break` 和 `continue` 语句无条件地退出一个代码块,它们之后的任何语句都不能被执行。不会用到的语句通常是一个错误。 diff --git a/src/rules/no-unsafe-negation.md b/src/rules/no-unsafe-negation.md index 0acc864..e39e2e5 100644 --- a/src/rules/no-unsafe-negation.md +++ b/src/rules/no-unsafe-negation.md @@ -1,6 +1,7 @@ --- title: no-unsafe-negation rule_type: problem +handled_by_typescript: true --- 就像开发者可能会输入 `-a + b`,而他们的意思是 `-(a + b)` 表示一个和的负数,他们可能会错误地输入 `!key in object`,而他们几乎肯定是指 `!(key in object)` 来测试一个键不在一个对象中。`!obj instanceof Ctor` 是类似的。