为TypeScript函数自动添加返回类型(VsCode插件)

317 阅读4分钟

0 概述

TypeScript Return Type Inference Plugin(VSCode插件) 通过推断并自动为 TypeScript 中没有显式声明返回类型的函数添加返回类型,从而帮助开发者减少与 typescript-eslint 中的 explicit-function-return-type 规则相关的警告和错误。

插件地址:marketplace.visualstudio.com/items?itemN…

Github(问题反馈):github.com/JoeWangzzz/…

1 背景

1.1 explicit-function-return-type

typescript-eslintexplicit-function-return-type 规则是一个用于强制 TypeScript 函数显式声明返回类型的规则。它确保每个函数、方法或 getter 都有明确的返回类型定义,而不是依赖 TypeScript 的类型推断。 explicit-function-return-type

1.2 如何为typescript函数快速添加返回类型声明?

1.2.1 typescript-eslint没有提供该规则的fixer

在2018年typescript-eslint下的issue下讨论了为什么 typescript-eslint不为explicit-function-return-type提供一个fixer github.com/typescript-…

  1. it forces the rule to need type information. 它强制规则需要类型信息。 没有其他方法可以在没有类型信息的情况下自动添加返回类型。
  2. a fixer won't work well beyond primitive and named types. 修复程序在原始类型和命名类型之外无法很好地工作 例如,如果您返回对象类型 return { a: { b: { c: 1 } } },那么自动修复程序将添加大量冗长的代码,而实际上可能有更好的类型可用。
  3. The spirit of the rule is for engineers to think clearly and establish explicit contracts with the functions they write.规则的精神是让工程师清晰地思考并与他们编写的函数建立明确的契约。

1.2.2 利用typescript提供的推断能力

实际上在VSCode中使用typescript开发,VSCode已经利用typescript为函数推断了返回类型,尽管有些情况下会遭遇1.2.1中第2条,推断类型冗长,但大多数情况下,该推断是“部分正确”的,至少也是对开发者声明正确的返回值有帮助的。

image.png

2 TypeScript Return Type Inference Plugin

2.1 功能

  • 自动推断函数返回类型:插件能够分析函数体,推断返回值类型,并自动为缺少返回类型的函数补全类型声明。
  • 作用范围配置:你可以选择在整个文件范围内操作,或只对光标所在的函数进行操作。
  • 支持的函数类型:插件支持不同类型的函数,包括 FunctionDeclarationFunctionExpressionArrowFunctionMethodDeclarationGetAccessorDeclaration

2.2 快捷键

  • 为整个文件的函数添加返回类型: 使用配置的快捷键(默认 Ctrl+Alt+i),当 scope 配置项设置为 file 时,插件会为当前文件中所有没有显式返回类型的函数自动添加返回类型。
  • 为光标所在的函数添加返回类型: 同样使用快捷键(默认 Ctrl+Alt+i),当 scope 配置项设置为 func 时,插件会在光标位置检测当前的函数定义,并为其自动添加返回类型。

2.3 插件配置

你可以通过 VSCode 的设置来配置该插件。可用的配置项如下:

  • scope(作用范围):可以设置为 filefunc

    • file:插件会为整个文件中的函数自动添加返回类型。
    • func:插件只会为当前光标所在的函数添加返回类型。
  • supportedFunctionTypes(支持的函数类型):声明插件支持的函数类型,可取以下值:

    • isFunctionDeclaration 函数声明
    • isFunctionExpression 函数表达式
    • isArrowFunction 箭头函数
    • isMethodDeclaration 方法声明
    • isGetAccessorDeclaration getter

2.4 原理

2.4.1 使用 TypeScript 编译器 API

插件通过 TypeScript 的编译器 API (typescript 模块) 解析 TypeScript 源文件,生成抽象语法树 (AST)。利用 createProgram 方法来处理当前工作区中的文件,并结合 TypeScript 的类型检查器 (TypeChecker),从函数的定义中推断返回值的类型。

2.4.2 类型推断

  • 当用户触发插件时,插件会找到当前文件中所有的函数声明(包括 FunctionDeclarationFunctionExpressionArrowFunctionMethodDeclarationGetAccessorDeclaration)。
  • 对于每个没有显式返回类型的函数,插件通过 TypeChecker.getTypeAtLocation() 方法获取该函数的返回值类型。
  • 返回类型会被转换为字符串形式,例如 ()=>void()=>number[],并被插入到函数的返回类型声明中。

3 未来工作

  1. 目前不支持工作区声明的namespace,优先考虑支持
  2. 提供推荐模式,对于复杂类型,根据“匹配”算法得出的可能类型的优先级,进行类型推荐,以避免添加冗长的代码

4 附录

关于explicit-function-return-type的配置:

explicit-function-return-type 规则允许通过配置文件调整严格程度。下面是一些常见的选项:

  • allowExpressions: 如果设置为 true,则允许在函数表达式和箭头函数中省略返回类型。
  • allowTypedFunctionExpressions: 允许在类型声明已经存在时(例如函数被赋值给某个带有显式类型的变量)省略返回类型。
  • allowHigherOrderFunctions: 允许高阶函数中的函数省略返回类型。
  • allowDirectConstAssertionInArrowFunctions: 允许在箭头函数中直接使用常量断言(const assertion),例如 const fn = () => 42 as const;