欢迎访问Sonar Source中文网站!
语言选择: ∷ 

无需编写 TypeScript 即可输入 JavaScript

发布时间:2023-10-25浏览次数:88

我们最近研究了如何在我们的 JavaScript 代码库中获得 TypeScript 的一些好处如果您已经完成了这个过程,那么 TypeScript 已经帮助您避免了 JavaScript 中的一些类型问题。但是,由于它作用于 JavaScript,TypeScript 将无法像它想要的那样进行推断。


好消息是,我们可以为 TypeScript 提供有关 JavaScript 应用程序周围类型的更多提示,而无需将项目更改为 TypeScript。

添加更多类型

一种方法是使用JSDocJSDoc 为您提供了一种通过机器可读的注释来记录代码的方法。它最初是为了为您的代码生成 API 文档而构建的,但 TypeScript 已采用它作为在 JavaScript 文件中提供类型信息的有效方式

JS文档

您可以使用 JSDoc 设置变量的类型。在此示例中,为变量分配一个空数组names不会告诉类型系统任何信息,但如果我们使用 JSDoc@type注释,那么我们会向 TypeScript 指示该变量应该只是一个字符串数组。由于这是文档,它还告诉您和您的团队这是什么类型的变量。

/**
 * @type {Array<string>}
 */let names = [];

如果您稍后尝试分配不同类型的值names或尝试添加错误类型的元素,TypeScript 会抱怨。

上面代码的屏幕截图,添加了一行,将数字推入名称数组中。 JavaScript 文件中显示 TypeScript 错误,指出“‘number’类型的参数无法分配给‘string’类型的参数。

您还可以使用@typedef定义复杂类型。 

/**
 * @typedef {object} TeamMember * @property {string} name - the full name of a team member
 * @property {Array<string>} languages - the programming languages the member knows
 *//**
 * @type {TeamMember}
 */const teamMember = {
  name: "Phil Nash",
  languages: ["JavaScript", "TypeScript", "CSS", "HTML"],};

有了 JSDoc 注释,您就可以将类型从一个文件导入到另一个文件中,这意味着您不必重复自己并在多个位置重新定义类型。


您还可以输入函数的参数和返回值:

/**
 * @typedef {import("./teamMember").TeamMember} TeamMember * @param {Array<TeamMember>} teamMembers - a list of team members
 * @returns {Array<string>}
 */function getNames(teamMembers) {
  return teamMembers.map(tm => tm.name);}
上述代码在 VS Code 中的屏幕截图。 对 tm 变量的 name 属性的调用会突出显示,并且弹出窗口显示 TypeScript 对代码的理解。 它显示为一个字符串,并从另一个文件中的 JSDoc 类型定义中提取文档。

JSDoc 的功能远不止这些,您可以在 TypeScript 文档 中阅读TypeScript 支持的 JSDoc 注释

TypeScript 声明文件

如果您发现在文件的注释中写入类型定义太吵闹,您可以选择将这些定义写入声明文件中。TypeScript 声明文件.d.ts文件,您可以在 Definely Typed 项目或也提供其类型定义的 JavaScript 库中找到。


编写 TypeScript 声明文件是本文最接近编写 TypeScript 本身的方法。声明文件以 TypeScript 语法声明类、函数和变量的类型,但不定义内容。


要使用声明文件来定义TeamMember类型,您可以从上面创建一个teamMember.d.ts文件并输入以下内容:

export type TeamMember = {
  name: string;
  languages: Array<string>;};

然后,您可以使用 JSDoc 导入语法将其导入到 JavaScript 中:

/**
 * @type {import("./teamMember.d").TeamMember}
 */const teamMember = {
  name: "John Doe",
  languages: ["JavaScript", "TypeScript", "HTML", "CSS"],};

从声明文件导入类型可以使类型定义与代码分离,并为您提供 TypeScript 类型系统的所有表达能力。将这样的声明文件添加到您编写的库中意味着其他项目也可以安装该库并访问类型。

仍然不是 TypeScript,只是增强了 JavaScript

请记住,您仍然处于 JavaScript 项目中。您不需要添加这些类型,但如果您发现代码的某些部分可以从它们中受益,那么 JavaScript、JSDoc 和声明文件(可选)的组合意味着您可以添加这些类型。


提供更多类型信息将有助于 TypeScript 更好地理解您的 JavaScript,进而帮助您的 IDE 提出更好的建议,并帮助SonarQube 和 SonarCloud 将 TypeScript 规则应用到您的源代码。


不过,请务必小心;在经历了这一演变之后,从将 TypeScript 添加到 JavaScript 项目并添加更多类型,您可能希望将项目一直转换为 TypeScript。值得庆幸的是,如果您已经走到这一步,那么移动的工作量现在要低得多,并且就像向代码库添加类型一样,可以增量地完成。


微信扫码微信扫码 关注我们

  • 24小时咨询热线180-210-69380

  • 移动电话180-210-69380

Copyright © 2022 All Rights Reserved. 地址:上海市浦东新区崮山路538号808 苏ICP123456 XML地图