纯 JS 也能支持静态类型

大家好,这里是大家的林语冰。

免责声明

本文属于是语冰的直男翻译了属于是,略有删改,仅供粉丝参考,英文原味版请传送 Get full type support with plain JavaScript

在 JS 的大型项目中,集成前端工具链的重要一环就是静态类型提示和检查,主流的有若干静态类型方案,包括但不限于:

  • Vue 等项目集成 TS
  • React 等项目集成 Flow
  • Svelte 等项目集成 JSDoc

TS 毫无疑问是 JS 静态类型的最佳实践,虽然但是,有时候不需要 TS 也可以享受静态类型带来的福利。

这听起来似曾相识:您想编写一个迷你脚本,无论是用于网络、命令行工具还是其他东东,然后从 JS 开始...... 直到您回忆起编写无类型的代码多么折磨。因此,您将文件从 .js 重命名为 .ts...... 并意识到您已经铸就了一坨"代码屎山"。

如果您正在为网站或库编写代码,那么您就需要编译步骤。如果您正在构建 CLI 脚本,您可以求助于 Deno(它支持开箱即用的 TS),但是您需要设置 IDE 来理解 Deno API,并且混用 Deno 和 Node 并非易如反掌。

一旦一切都在本地运行,您需要考虑如何分发代码。您是否签入编译的 .js 文件?您是否创建 CI 管道来自动编译 .ts 文件?如果您正在编写一个库,您如何发布您的库,以便可供其他项目使用?

您实际上不需要 TS

问题在于 ------ 您不需要编写 TS,也可以获得静态类型分析!

通过使用 JSDoc,您可以在 JS 中获得 TS 的所有福利

TS 提供的是静态类型系统。这意味着,类型信息对运行代码没有影响。当执行 TS 时,所有类型信息都将完全丢失(这就是为什么在不编写类型守卫的情况下,无法测试变量是否属于某种类型的原因)。

这也意味着,TS 只是提供给 TS 分析器的附加类型信息,对运行代码的 JS 引擎没有任何意义。当您将 TS 编译为 JS 时,它基本上只是从代码中删除所有类型信息,使其再次成为有效的 JS 代码。

JSDoc

JS 破蛋三年后 JSDoc 被引入,作为一种注释 JS 代码的方式。它是一种形式化标记语言,允许 IDE 在开发者瞄到某个函数时,向它们提供额外的上下文。

大多数语言中都存在类似的注释标记,我相信您已经知道了。它看起来是这样的:

js 复制代码
/**
 * 此处是 JSDoc 区块。IDE 会在您悬停在 printName 函数时展示此文本。
 *
 * @param {string} name
 */
function printName(name) {
  console.log(name)
}

TS vs JSDoc

鲜为人知的是,JSDoc 是充分利用 TS 所需的一切。 TS 分析器可以理解 JSDoc 中编写的类型,并为您提供与 .ts 文件相同的静态分析。

JSDoc 的类型语法

我不会在这里提供语法的完整文档。最重要的是您知道,您可以在 .ts 文件中执行的几乎所有操作都可以使用 JSDoc 执行。但这里有几个例子:

js 复制代码
/**
 * @param {string} a
 * @param {number} b
 */
function foo(a, b) {}

使用 TS 提供的开箱即用类型:

js 复制代码
/**
 * @param {HTMLElement} element
 * @param {Window} window
 */
function foo(element, window) {}

/** @type {number[]} */
let years

定义对象字面量和函数:

js 复制代码
/** @type {{ name: string; age: number }} */
let person

/** @type {(s: string, b: boolean) => void} */
let myCallback

*.d.ts 文件导入类型:

js 复制代码
/** @param {import('./types').User} user */
const deleteUser = user => {}

定义一个类型供以后使用:

js 复制代码
/**
 * @typedef {object} Color
 * @property {number} chroma
 * @property {number} hue
 */

/** @type {Color[]} */
const colors = [
  { chroma: 0.2, hue: 262 },
  { chroma: 0.2, hue: 28.3 }
]

如果您有复杂的类型,您仍然可以编写 *.d.ts 文件,并将其导入到 JSDoc 注释中

粉丝请注意,您仍然需要为 TS 设置项目(和 IDE),并且需要创建一个 tsconfig.json 文件,并将编译器选项 allowJscheckJs 设置为 true 的:

json 复制代码
// tsconfig.json
{
  "compilerOptions": {
    "allowJs": true,
    "checkJs": true
    // ...
  }
}

何时优先使用 TS

尽管可以专门使用 JSDoc 进行类型声明,但这并不是最方便的。TS 的语法更棒,且重复性更少。

TS 团队创建了一个"类型作为注释" ECMAScript 提案,允许您编写 TS,并在 JS 引擎中运行它而无需修改(JS 引擎会将这些类型注释视为注释。)

但在该提案被接受之前,我们要么选用 JSDoc,要么选用 TS 工具链。

所以,目前我的建议是:当您正在处理一个无论如何都有编译步骤的项目时,使用 TS 完美无缺。这包括您想要优化生产脚本的典型网站。

如果您不需要编译步骤,那么使用 JSDoc 的类型注释可能会更容易。

您现在收看的是《前端翻译计划》,学废了的小伙伴可以订阅此专栏合集,我们每天佛系投稿,欢迎持续关注前端生态。谢谢大家的点赞,掰掰~

相关推荐
小闫BI设源码7 分钟前
uniapp中的事件:v-on
前端·vue.js·uni-app
学习前端的小z9 分钟前
【前端】JavaScript中的字面量概念与应用详解
javascript
夏天想22 分钟前
vue路由的几种模式。有什么区别
前端·javascript·vue.js
家有狸花39 分钟前
CSS笔记(二)类名复用
javascript·css·笔记
一条破秋裤1 小时前
关于使用天地图、leaflet、ENVI、Vue工具实现 前端地图上覆盖上处理的农业地块图层任务
前端·javascript·vue.js
开花大馒头1 小时前
本地学习axios源码-如何在本地打印axios里面的信息
前端·react.js
徐同保1 小时前
web3.js + Ganache 模拟以太坊账户间转账
开发语言·javascript·web3
三门1 小时前
k3s入门--踩坑解决AutoK3s运行K3d集群
前端
永乐春秋1 小时前
WEB攻防-通用漏洞&XSS跨站&MXSS&UXSS&FlashXSS&PDFXSS
前端·xss
hummhumm1 小时前
第 38 章 -GO语言 事件驱动架构
java·javascript·后端·python·架构·golang·ruby