Skip to content

报错的时候终止 js 文件的生成

TypeScript 编译的时候即使报错了,还是会生成编译结果,我们仍然可以使用这个编译之后的文件。

如果要在报错的时候终止 js 文件的生成,可以在 tsconfig.json 中配置 noEmitOnError 即可。

自动生成声明文件

如果库的源码本身就是由 ts 写的,那么在使用 tsc 脚本将 ts 编译为 js 的时候,添加 declaration 选项,就可以同时也生成 .d.ts 声明文件了。

我们可以在命令行中添加 --declaration(简写 -d),或者在 tsconfig.json 中添加 declaration 选项。这里以 tsconfig.json 为例:

json
{
    "compilerOptions": {
        "module": "commonjs",
        "outDir": "lib",
        "declaration": true,
    }
}

上例中我们添加了 outDir 选项,将 ts 文件的编译结果输出到 lib 目录下,然后添加了 declaration 选项,设置为 true,表示将会由 ts 文件自动生成 .d.ts 声明文件,也会输出到 lib 目录下。

运行 tsc 之后,目录结构如下:

/path/to/project
├── lib
|  ├── bar
|  |  ├── index.d.ts
|  |  └── index.js
|  ├── index.d.ts
|  └── index.js
├── src
|  ├── bar
|  |  └── index.ts
|  └── index.ts
├── package.json
└── tsconfig.json

在这个例子中,src 目录下有两个 ts 文件,分别是 src/index.ts 和 src/bar/index.ts,它们被编译到 lib 目录下的同时,也会生成对应的两个声明文件 lib/index.d.ts 和 lib/bar/index.d.ts。它们的内容分别是:

ts
// src/index.ts

export * from './bar';

export default function foo() {
    return 'foo';
}
ts
// src/bar/index.ts

export function bar() {
    return 'bar';
}
ts
// lib/index.d.ts

export * from './bar';
export default function foo(): string;
ts
// lib/bar/index.d.ts

export declare function bar(): string;

可见,自动生成的声明文件基本保持了源码的结构,而将具体实现去掉了,生成了对应的类型声明。

使用 tsc 自动生成声明文件时,每个 ts 文件都会对应一个 .d.ts 声明文件。这样的好处是,使用方不仅可以在使用 import foo from 'foo' 导入默认的模块时获得类型提示,还可以在使用 import bar from 'foo/lib/bar' 导入一个子模块时,也获得对应的类型提示。

除了 declaration 选项之外,还有几个选项也与自动生成声明文件有关,这里只简单列举出来,不做详细演示了:

  • declarationDir 设置生成 .d.ts 文件的目录
  • declarationMap 对每个 .d.ts 文件,都生成对应的 .d.ts.map(sourcemap)文件
  • emitDeclarationOnly 仅生成 .d.ts 文件,不生成 .js 文件

tsconfig.json 配置文件

json
{
  // ts 编译为 js 的配置选项
  "compilerOptions": {
    // ts 编译为目标 js 的语法版本。设置为高版本或许可以提高转换速度。
    // 我们并不需要 ts 来做代码兼容。代码兼容交给 babel 来做。
    "target": "ESNext",
    // 是否启用 class fields 语法。
    // 实际上在新版 ts 里已经支持 class fields 语法。
    // 所以在新版这个配置无效,使用 class fields 语法不会报错。
    "useDefineForClassFields": false,
    // 支持环境 api。比如要运行到浏览器里,那么需要包含浏览器 document 相关的 api。
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    // 允许 js 文件被引入到 ts 文件。
    "allowJs": false,
    // 跳过对声明文件 (扩展名为 .d.ts 的文件) 的类型检查。缩短编译时间
    "skipLibCheck": true,
    // 支持合成默认导入。使 esm 里支持 cjs 模块。
    "esModuleInterop": false,
    // 允许合成默认导出。在 esm 里,支持 cjs 默认导出
    "allowSyntheticDefaultImports": true,
    // 下面七个配置的总配置。优先级低。
    "strict": true,
    // 不允许隐式 any 类型
    "noImplicitAny": true,
    // 严格检查 null 类型
    "strictNullChecks": true, 
    // 严格函数类型
    // function getCurrentYear(callback: (date: string | number) => void) {
    //   callback(Math.random() > 0.5 ? '2020' : 2020)
    // }
    // getCurrentYear((date: string) => {
    //   console.log(date.charAt(0))
    // })
    "strictFunctionTypes": true,
    // 使用 bind、call 和 apply 语法的时候,是否进行参数检查
    "strictBindCallApply": true,
    // 这个选项要和 strictNullChecks 配合使用才行。该选项用于检查类的属性是否被初始化,如果开启则必须进行初始化。
    "strictPropertyInitialization": true,
    // 不允许出现隐式 any 类型的 this  
    "noImplicitThis": true,
    // 就是 JavaScript 中的 "use strict",肯定是要开启的
    "alwaysStrict": true,
    // 强制引入文件名的大小写一致。防止对大小写敏感的系统出错。
    "forceConsistentCasingInFileNames": true,
    // 默认值为 none。打包工具会处理成符合规范的模块化代码。
    "module": "ESNext",
    // 模块导入解析策略。node 会在 node_modules 里去找。
    "moduleResolution": "Node",
    // 是否支持引入 json 文件
    "resolveJsonModule": true,
    // 强制要求导入、导出类型都加上 type
    "isolatedModules": true,
    // 不输出转化后的 js 文件
    "noEmit": true,
    // TS 具有三种 JSX 模式:preserve,react 和 react-native
    // 在 preserve 模式下生成代码中会保留 JSX 以供后续的转换操作使用
    // react 模式会生成 React.createElement,在使用前不需要再进行转换操作了
    // react-native 相当于 preserve,它也保留了所有的 JSX,但是输出文件的扩展名是.js
    "jsx": "react-jsx",
    // 设置路径文件名,用于项目中路径简写
    "paths": {
      "@/*": ["./src/*"]
    },
  },
  // include 字段用于指明需要被 tsc 编译的文件或文件夹列表,例如:
  "include": ["src"],
  // “项目引用(Project References)”功能,它允许用户为项目的不同部分使用不同的 TypeScript 配置。
  "references": [{ "path": "./tsconfig.node.json" }]
}

Released under the MIT License.