Skip to content
0

Typescript

TypeScript 也是工程化的重要一环,在面对复杂功能代码设计的时候,足够熟悉 TS 能够帮我们更加安全快速地实现。

关于 TS 有数不尽的教程,所以在假设您已经掌握基本语法的情况下,让我们开始探索一些有趣的东西。

附上一篇教程: https://wangdoc.com/typescript/

tsc

tscTypeScript 官方的命令行编译器,拥有编译,检查,生成类型定义文件的功能

$ tsc src/*.ts

上面的命令就可以将 TS 文件编译为 JS 文件,但是在前端功能中,我们很少会使用这个功能,而是采用其他工具,例如 rollupesbuild 等进行文件等转换:

$ esbuild src/*.ts --outdir=dist

在前端工程中,tsc 的用途通常是进行 TS 的类型校验,因为上面的工具例如 esbuild 只进行文件类型转换,抹去 TS 类型,而不做任何类型校验。

例如我们通常会在 scripts 加上这段脚本,仅仅对类型进行校验,--noEmit 的作用是不生成编译产物,只进行类型检查

{
    "scripts": {
        "typecheck": "tsc --noEmit"
    }
}

dts生成

对应一般情况,可以使用 tsup 的生成功能

$ tsup src/index.ts --dtsOnly

或者是直接使用 tsc

$ tsc src/index.ts --emitDeclarationOnly --declaration --outDir dist
$ tsc src/index.ts --emitDeclarationOnly --declaration --outFile ./index.d.ts  # 合并成一个文件

类似的,有 johnsoncodehk/vue-tsc 来支持 vue 相关的 dts 生成

$ vue-tsc src/index.ts --emitDeclarationOnly --declaration --outDir dist
$ vue-tsc src/index.ts --emitDeclarationOnly --declaration --outFile ./index.d.ts  # 合并成一个文件

至于 JS 和 SouceMap 等产物的生成,交由打包工具去生成,我们仅用 tsc 进行类型检查

扩展类型

在 NodeJs 中,我们通过安装 @types/node 来获得 NodeJs 环境 API 的类型提示

但是如果我们想扩展一个类型怎么办呢,譬如为环境添加 process.env.NODE_ENV,原生环境中是不存在这个变量的

借助于 TS 中两个同样的 interface 声明会被合并的特性,就可以实现扩展

interface IPeople {
    name: string
}

interface IPeople {
    age: number
}

let o: IPeople = {
    name: 'mike',
    age: 10
}

但是 process.env.NODE_ENV 是一个嵌套的对象,所以需要找到 ProcessEnv 类型定义所在的命名空间,在进行扩展

通过 declare 关键字,扩展 ProcessEnv 类型

declare global {
    namespace NodeJs {
        interface ProcessEnv {
            NODE_ENV: 'development' | 'production'
        }
    }
}

// 扩展 window 的类型
declare global {
    interface window {
        time: number;
    }
}

类型声明

如上面所展示的,借助 declare,我们可以不必在变量定义的时候就定义类型。所以类似的,除了扩展类型,还可以定义类型

foo = 2
declare let foo: number

// 或者是函数
declare let bar: () => number
bar()

扩展模块类型

某些模块,比如某些 NPM 包,没有提供类型声明文件,我们可以扩展模块的类型,定义里面的模块的类型

declare module 'module1' {
  function log(): string
}

declare module 'module2' // 声明后,默认导出默认是 any
import m_1 from 'module1'
import m_2 from 'module2'

m_1.log()

以此来消除 TS 错误

package.json 的 types 字段

发布 NPM 包这一节中,提到了在 package.json 中添加 types 字段,指明一个 .d.ts 文件,就可以为当前模块定义类型了。

Details
json
{
  "name": "transform-size-data",
  "version": "1.0.0",
  "type": "module",
  "types": "./dist/index.d.ts",
  "author": "peterroe",
  "module": "./dist/index.mjs",
  "main": "./dist/index.cjs",
  "exports": {
    ".": {
      "require": "./dist/index.cjs",
      "import": "./dist/index.mjs"
    }
  }
}

本质上就是隐式地声明了 declare module 'transform-size-data',来定义类型的,让使用者能够获得正确的类型

declare module 'transform-size-data' {
    // ./dist/index.d.ts 的内容
}

tsconfig.json

这里有一份较为详细的 tsconfig.json 说明,这些配置除了给 tsc 读取,其他打包工具也会使用其中的某些字段

下面只介绍一些常用的字段

target

target 指定编译出来的 JavaScript 代码的 ECMAScript 版本,一般设置为 esnext。(esbuild 依赖)

{
    "compilerOptions": {
        "target": "esnext"
    }
}

Released under the MIT License.