node.js 脚本如何使用Typescript优化

1,965 阅读5分钟

node.js 脚本如何使用Typescript

Typescript能够补充类型,这对于脚本工具具有一定的帮助,当我们开发的时候,不记得具体的类型,TS能够直接推断出来,避免写一写去查查类型问题,对吧🐈。 下面主要介绍,如何用TS来写node.js脚本代码。

1、主体思路

0 前序步骤,将工程配置完毕 1 编写TS代码 2 通过ts-node进行调试 3 编译为js脚本进行相关的后续工作

2、如何调试ts-node tsserver

ts-node(npm文档)这个工具非常好,能够帮助你调试TS脚本,避免频繁编译。
typescript还有个tsserver类似与webpack server。

2.1 单一文件如何调试

这里常用的是--project 选项,它填写的参数是配置文件的路径。通过它引用相关配置文件。

ts-node --project tsconfig.json ${MY_WORKSPACE}/test.ts

2.2 vscode如何调试

vscode上面调试讲两点:

1 调试ts文件

调试ts文件按照ts-node文档里面配置的就可以,具体操作为,将下面的配置文件放到,${MY_WORKSPACE}/.vscode/launch.json中的configurations属性里面就行了。

{
      "type": "node",
      "request": "launch",
      "name": "调试ts-node",
      "runtimeArgs": ["-r", "ts-node/register"],
      "args": ["${workspaceFolder}/src/test.ts"],
      "env": { "TS_NODE_PROJECT": "tsconfig.json" }
}

注意:如果想要引入自定义的tsconfig.js文件,需要使用env相关参数

2 调试命令行

调试命令行,最开始我也没转换过来思路,但是后来想了一下,其实就是调试处理命令行命令的脚本。思路就是直接调用相关脚本,然后在args中传入你的脚本参数就可以啦。

{
      "type": "node",
      "request": "launch",
      "name": "调试命令行",
      "program": "${workspaceFolder}/bin/index.js",
      "args": ["arg1"]
}

2.3 tsserver

我用下面的命令来实现devserver的效果。tsserver是TS自带。

tsc -w -p tsconfig.json

3、配置文件相关

示例配置文件:

{
  "compilerOptions": {
    "allowJs": true,
    "target": "es2015",
    "module": "commonjs", 
    //module 按照什么形式编辑  "None", "CommonJS", "AMD", "System", "UMD", "ES6"或 "ES2015"
    "lib": ["es6", "es2015"],
    // 编译中可能需要的库
    "outDir": "build", //输出位置
    "baseUrl": ".", // 与 "paths" 紧密相关
    "typeRoots": ["node_modules/@types", "typings/*"],
    "moduleResolution": "Node", //如何处理模块的引用
    "paths": { // 文件映射
      "*": ["src/*", "typings"]
    }
  },
  "include": ["./src"],
  "exclude": [
    "node_modules",
    ".vscode",
    "build",
    "bin",
    "doc"
  ]
}

上面是我用到的配置文件,下面梳理一下主要参数:

1 baseUrl

baseUrl是解析文件相对路径的基准路径。 举例,如果我要解析"my/module",且baseUrl是".",那么得到的实际路径就是${BaseURL的实际路径}/my/module。

2 rootDirs

它只是表示一个虚拟路径,下面的代码是TS官网的示例,如果我们只需要src文件夹和generated/templates/views文件夹那么就可以用rootDirs把后面的文件夹级别提高,避免我们引用的时候路径过长。(对于我来讲用path也行,这个的用处暂时还没想通。)

 src
 └── views
     └── view1.ts (imports './template1')
     └── view2.ts

 generated
 └── templates
         └── views
             └── template1.ts (imports './view2')

3 @types,typeRoots和types

名称 意义
@types 默认设置,也就是node安装的type。node_modules/@types文件夹下以及它们子文件夹下的所有包都是可见的;举例 ./node_modules/@types/../node_modules/@types/../../node_modules/@types/等等。
typeRoots 如果指定了typeRoots只有typeRoots下面的包才会被包含进来。 我们需要单独把上面的type再引入一次。
types 如果指定了types,只有被列出来的包才会被包含进来。举例: "types" : ["node", "lodash", "express"]

4 paths

文件的路径映射,需要和baseUrl配合使用。 如果 "baseUrl"被设置成了除"."外的其它值,比如/src所在的目录,那么映射必须要做相应的改变。就会从src继续向下去找。

5 typeroots not working?

在配置的时候总会遇到一个问题 typeroots not working,在前面的参数弄清楚之后,发现了问题所在。我想只将src目录下的代码进行编译,但是直接改了baseurl到src/类型文件就不会引用进来,正确做法应该是加上paths文件并将typings文件引入即可,具体你可以查看配置文件思考一下就明白了,通过paths引用也将d.ts引用进来了。你可以做个实验,将d.ts放到src里面在将baseUrl改为src你也可以编译。

参考连接:
1 github.com/microsoft/T…
2 stackoverflow.com/questions/5…

4 模块解析

TS官网模块解析相关
在写TS网页的时候,一切都很顺利,但是到TS解析的时候问题就又出来了。

1 如何用module.exports

首先看TS官网的一句话

TypeScript与ECMAScript 2015一样,任何包含顶级import或者export的文件都被当成一个模块。相反地,如果一个文件不带有顶级的import或者export声明,那么它的内容被视为全局可见的(因此对模块也是可见的)。

这句话解决了我的一个问题,如果你想用modules.exports,那么必须加上作用域,如果不加作用域那么会认为全局可见产生多次引用报错

image.png

2 如何用exports

还是引用一句话

CommonJS和AMD的exports都可以被赋值为一个对象, 这种情况下其作用就类似于 es6 语法里的默认导出,即 export default语法了。虽然作用相似,但是 export default 语法并不能兼容CommonJS和AMD的exports。 为了支持CommonJS和AMD的exports, TypeScript提供了export =语法。export =语法定义一个模块的导出对象。 这里的对象一词指的是类,接口,命名空间,函数或枚举。 若使用export =导出一个模块,则必须使用TypeScript的特定语法import module = require("module")来导入此模块。

我没有使用这个,感觉语法和普通脚本差异更大,不利于交流。

3 import/export

最开始我使用的是module.exports加上命名空间的方式,虽然成功写出来了但是有个问题,通过module.exports引入的代码后面的类型推断不出来了。

在实验以及参考了部分Typescript源码之后发现,需要命名空间配合import/export一起使用更好。

从我的经验来看,一些API类,数据传输类用了效果很好,因为他会加上类型推断,但是有些动态引用或者是bin的index文件用起来不太好,与脚本形式差异较大。

5 如何编译正式版本

目前我的做法是,将代码编译到指定位置然后用bin/index.js ,也就是处理命令行脚本的js来引用编译后的文件达到目的。


欢迎大家指正~~~ 🐱🐶