前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入理解 isolatedDeclarations

深入理解 isolatedDeclarations

作者头像
不换
发布2024-07-16 14:14:14
780
发布2024-07-16 14:14:14
举报
文章被收录于专栏:不换的随想乐园

深入理解 isolatedDeclarations

在上周的周刊(Weekly 第 50 期[1])中我们有介绍到 TypeScript 中的 isolatedDeclarations 配置项。起初决定深入研究的来源是一篇快报文章中[2]的:

文章的名称翻译下:“加速 JavaScript 生态系统 - 独立声明”,简单明了。

但是这篇文章中的作者少说了一个 API,而且该文章作者使用的是 deno,天然支持 TypeScript

文章中有这么一句话:“免责声明,我的环境在 deno”,说明并未在 Node 环境中真实的体验过这个特性以及背后产生的动机。

好了,我们步入正题。这里聊一个辅车相依,唇亡齿寒的问题,那就是 isolatedDeclarationstranspileDeclaration 配对使用才可以在上层编译打包工具开发中发挥最大的优势。

或者可以摒弃 transpileDeclaration ,借助 孤立声明信任度 自己写解析器也不是不可以(刚好社区就有一个用 rust 写的 oxc-transform[3])。

当然对于使用者而言是无感的,这部分用户是无所谓的(假如这时候社区的绝大部分工具已经相当完善了,比如 @rollup/rollup-plugin-dts 等工具)

本篇文章的环境信息为 Mac OS m2,相关工具版本为 TypeScript v5.5.3Node v21.1.0

TypeScript 代码库进行类型检查可能会很慢,尤其是对于包含大量项目的 monorepos,每个项目都需要使用类型检查器来生成类型声明文件。“隔离声明”的 TypeScript 新功能,该功能允许在完全不使用类型检查器的情况下生成 DTS 文件!

isolatedDeclarations 出现的动机

几个维度:用户声明文件底层工具创作者声明文件的在上层工具中生成的创作者

  1. 对用户而言,理解 isolatedDeclarations ,并且知道这个配置项需要你的文件在导出时充分注释,否则它会让 TypeScript 报告错误。(必须充分注释类型,而不是常规情况下的自动推导 (如 any))
    • 注意:不要期待加了这个配置项能有什么奇妙的事情发生(比如加快什么速度.....)
  2. 对声明文件底层工具创作者而言,可以创建更快的工具,因为你可以借助 transpileDeclaration 来构建声明文件。
    • 中间没有任何的 语法 check编译 ts 为 js,很纯粹的快。
  3. 对声明文件的在上层工具中生成的创作者而言,可以让任务并行,来取得 DX 体验升级 或者 CI/CD 的速度加快。
    • 例如 monorepo 的仓库维护者,可以让构建和 DTS 的声明相关的任务并行执行。

具体的介绍以及讨论详见 `Issue 58944`[4]

isolatedDeclarations 的使用

代码语言:javascript
复制
{
  "extends": ["../../tsconfig.json"],
  "compilerOptions": {
    "baseUrl": "./",
    "declarationDir": "./lib",
    "isolatedDeclarations": true,
    "composite": true
  },
  "include": ["src"]
}

如果有语法错误,我们大概会在 IDE 中看到如下错误:

transpileDeclaration 的使用

关于此 API 的介绍以及讨论详见`Issue 58261`[5]

代码语言:javascript
复制
import { transpileDeclaration } from 'typescript';
const dts = transpileDeclaration(code, {
});

实战

我们就以第三视角 声明文件的在上层工具中生成的创作者,以 Monorepo 为例,这里借助 rollup v4 进行打包,自定义一个插件,姑且就叫 rollup-plugin-dts 吧。

代码语言:javascript
复制
import { transpileDeclaration } from 'typescript';
import { createFilter } from '@rollup/pluginutils';

import { consola } from "consola";

function generateDTS(options = {}) {
    return {
        name: "generateDTS",
        buildStart() {
            this.DTSTimeStart = Date.now();
            consola.info("Generate DTS Start");
        },
        buildEnd() {
            consola.success("Generate DTS End,Time Delay: ", Date.now() - this.DTSTimeStart, "ms");
        },
        transform(code, id) {
            const filter = createFilter(options.include, options.exclude);
            if (!filter(id)) return;
            const [path, ext]  = id.split(".");
            const [fileName] = path.split('/').slice(-1)
            if(ext === 'ts') {
                const dts = transpileDeclaration(code, {});
                this.emitFile({
                    type: 'asset',
                    fileName: `${fileName}.d.ts`,
                    source: dts.outputText
                })
            }
            return  {
                code: code,
                map: null
            };
        }
    }
}

export  default  generateDTS


执行 pnpm run build 命令,最终可以观察到。

最终输出时间为:80+ms

实现原理

源码来自:Source Code: `src/services/transpile.ts`[6]

代码语言:javascript
复制
/*
 * This function will create a declaration file from 'input' argument using specified compiler options.
 * If no options are provided - it will use a set of default compiler options.
 * Extra compiler options that will unconditionally be used by this function are:
 * - isolatedDeclarations = true
 * - isolatedModules = true
 * - allowNonTsExtensions = true
 * - noLib = true
 * - noResolve = true
 * - declaration = true
 * - emitDeclarationOnly = true
 * Note that this declaration file may differ from one produced by a full program typecheck,
 * in that only types in the single input file are available to be used in the generated declarations.
 */
export function transpileDeclaration(input: string, transpileOptions: TranspileOptions): TranspileOutput {
    return transpileWorker(input, transpileOptions, /*declaration*/ true);
}

源码来自:Source Code: `src/services/transpile.ts`[7]

代码语言:javascript
复制
const result = program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ declaration, transpileOptions.transformers, /*forceDtsEmit*/ declaration);

我对 TypeScript 底层的源码研究不多,但是看下来基本是换汤不换药,没做底层的大改动,基于原来的底层方法,扩展了配置,分隔了一个方法出来,专门做声明文件的生成。

心智模型

TypeScript 官网提供了两个 Case:

相关地址:https://devblogs.microsoft.com/typescript/announcing-typescript-5-5-beta/#isolated-declarations

更快的声明生成
  • 痛点:依赖文件生成
  • 目标:只生成主文件导出声明,而无需关心依赖项的声明类型

举个例子:

代码语言:javascript
复制
// util.ts
export let one = "1";
export let two = "2";

// add.ts
import { one, two } from "./util";
export function add() { return one + two; }

对于咱们应用而言,add.ts 作为主入口,那么,只需要声明 add() 的返回类型即可,这样就不用递归解析去推导类型了。

我个人认为这种模式是相当合理的,特别是作为库开发者,动动手就能解决一些痛点。

并行检查&并行声明生成

如上:frontedbackend 都依赖 core,通过拓扑依赖的解析顺序而言,先要解析 core ,再解析 frontedfronted

这个时候,虽然可以并行执行 fronted & backend,但是必须同步等 core,且这个解析动作包含了 类型检查类型声明的生成以及推导,也就有了痛点

所以这就体现了孤立声明的好处,类型检查文件声明生成并行执行,不用等 tsc 等工具的 检查生成 同时 OK

小结

isolatedDeclarationstranspileDeclaration 确实是一次对工具层的革新,期待在 TypeScript 5.6 版本中更加成熟。

最后,我是不换,本期探究到此结束啦,如有勘误可以在博客下方留言板留言,期待下篇博客再见 👋

参考资料

[1]

Weekly 第 50 期: https://weekly.binlin.wang/docs/2024/07/50/

[2]

快报文章中: https://marvinh.dev/blog/speeding-up-javascript-ecosystem-part-10/

[3]

oxc-transform: https://github.com/oxc-project/oxc/blob/main/npm/oxc-transform/scripts/generate-packages.mjs

[4]

Issue 58944: https://github.com/microsoft/TypeScript/issues/58944

[5]

Issue 58261: https://github.com/microsoft/TypeScript/pull/58261

[6]

Source Code: src/services/transpile.ts: https://github.com/microsoft/TypeScript/pull/58261/files#diff-8b9f3ad376989ea0de53dc29981105e71f6f3ba51c72ab811f267dc414621808R64

[7]

Source Code: src/services/transpile.ts: https://github.com/microsoft/TypeScript/pull/58261/files#diff-8b9f3ad376989ea0de53dc29981105e71f6f3ba51c72ab811f267dc414621808R64

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 不换的随想乐园 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 深入理解 isolatedDeclarations
  • isolatedDeclarations 出现的动机
  • isolatedDeclarations 的使用
  • transpileDeclaration 的使用
  • 实战
  • 实现原理
  • 心智模型
    • 更快的声明生成
      • 并行检查&并行声明生成
      • 小结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档