环境:Mac OS
前置条件:已安装 node 和 npm
开发工具: VS Code
安装与调试
全局安装 ts 和 ts-node
npm install typescript@2.9.2 -g
npm install ts-node@7.0.0 -g
记录下安装完 ts-node 之后的可执行文件路径。
新建一个目录 tsdemo,并在其中新建一个 1.ts 文件,在文件中写 console.log('Hello, TS!')
然后保存。
Windows 用户注意,这里需要单独运行一些命令(Linux 用户和 macOS 用户不用执行)
npm init -y
npm i -D ts-node typescript
在 tsdemo 下创建 .vscode 目录,在其中创建 launch.json ,内容如下:
{
"configurations": [
{
"name": "ts-node",
"type": "node",
"request": "launch",
"program": "注意这里,要写成ts-node对应的可执行文件;Windows 用户注意,应该写成 ${workspaceRoot}/node_modules/ts-node/dist/bin.js",
"args": ["${relativeFile}"],
"cwd": "${workspaceRoot}",
"protocol": "inspector"
}
]
}
使用 VS Code 打开 tsdemo 下的 1.ts,找到调试,
看到结果后说明调试正常(注意选中的文件确定是 1.ts)。
命令行程序
在 tsdemo 下新建一个 add.ts 文件
#!/usr/bin/env ts-node
console.log('hello world')
#!/usr/bin/env ts-node
这一行注释代码有历史渊源,叫 shebang
然后给 add.ts 文件添加执行权限(Windows 用户不需要做这个,直接在 Git Bash 输入 ./1.ts 即可运行):
chmod +x ./1.ts
执行 ./1.ts
,输出 'hello world'
之后说明正常。
在 add.ts 中继续写代码:
#!/usr/bin/env ts-node
console.log('hello world')
console.log(process.argv)
此时再运行会报错:
/usr/local/lib/node_modules/ts-node/src/index.ts:261
return new TSError(diagnosticText, diagnosticCodes)
^
TSError: ⨯ Unable to compile TypeScript:
2.ts(2,13): error TS2304: Cannot find name 'process'.
at createTSError (/usr/local/lib/node_modules/ts-node/src/index.ts:261:12)
at getOutput (/usr/local/lib/node_modules/ts-node/src/index.ts:367:40)
at Object.compile (/usr/local/lib/node_modules/ts-node/src/index.ts:557:11)
at Module.m._compile (/usr/local/lib/node_modules/ts-node/src/index.ts:439:43)
at Module._extensions..js (module.js:663:10)
at Object.require.extensions.(anonymous function) [as .ts] (/usr/local/lib/node_modules/ts-node/src/index.ts:442:12)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Function.Module.runMain (module.js:693:10)
process 是 Node.js 的全局变量,不可能找不到。其实原因是没有相关的类型声明。
这就是 TS 的厉害之处:如果你不告诉我 process 是什么,我就不允许你用 process。
那么如何告诉 TS process 是什么呢?
方法如下:
# 初始化项目的 package.json
> npm init -y
# 安装 node 相关的类型定义
> npm install @types/node
# 再次运行 ./add.ts
> ./add.ts
[ 'node', '/Users/frank/TypeScript/tsdemo/2.ts' ]
就可以了。
现在终于轮到写正常的代码了。
#!/usr/bin/env ts-node
function add(a: number, b: number): number {
return a + b
}
const a = parseInt(process.argv[2])
const b = parseInt(process.argv[3])
if (Number.isNaN(a) || Number.isNaN(b)) {
console.log('参数错误')
process.exit(1)
}
console.log(add(a, b))
// 0一般代表程序正常执行结束
// 非0代表程序出错
// 正所谓幸福的家庭都是相似的,不幸的家庭却各有各的不幸
process.exit(0)
噢,还不行,执行后发现又报错了,
/Users/lijingwei/.nvm/versions/node/v14.16.1/lib/node_modules/ts-node/src/index.ts:261
return new TSError(diagnosticText, diagnosticCodes)
^
TSError: ⨯ Unable to compile TypeScript:
1.ts(9,12): error TS2339: Property 'isNaN' does not exist on type 'NumberConstructor'.
1.ts(9,31): error TS2339: Property 'isNaN' does not exist on type 'NumberConstructor'.
at createTSError (/Users/lijingwei/.nvm/versions/node/v14.16.1/lib/node_modules/ts-node/src/index.ts:261:12)
at getOutput (/Users/lijingwei/.nvm/versions/node/v14.16.1/lib/node_modules/ts-node/src/index.ts:367:40)
at Object.compile (/Users/lijingwei/.nvm/versions/node/v14.16.1/lib/node_modules/ts-node/src/index.ts:557:11)
at Module.m._compile (/Users/lijingwei/.nvm/versions/node/v14.16.1/lib/node_modules/ts-node/src/index.ts:439:43)
at Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Object.require.extensions.<computed> [as .ts] (/Users/lijingwei/.nvm/versions/node/v14.16.1/lib/node_modules/ts-node/src/index.ts:442:12)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
at Object.<anonymous> (/Users/lijingwei/.nvm/versions/node/v14.16.1/lib/node_modules/ts-node/src/bin.ts:147:12)
原因是代码里使用了 Number.isNaN
这个新语法,ts 虽然默认支持,但是必须配置之后才可使用。
配置的方法是在 tsdemo 目录下新建一个 tsconfig.json 文件:
{
"compilerOptions": {
"lib": ["ES2015"]
}
}
此时再执行 ./add.ts 1 2
即可正常执行。
TS 第二天
写一个 tree.ts 。
#!/usr/bin/env ts-node
function createPrefix(n: number): string {
return '----'.repeat(n)
}
class Person {
// 默认值
public children: Person[] = []
constructor(public name: string) { }
// 函数返回值为空
addChild(child: Person): void {
this.children.push(child)
}
// 接收可选参数
introduceFamily(n?: number): void {
n = n || 1
console.log(`${createPrefix(n - 1)}${this.name}`)
this.children.forEach(child => {
child.introduceFamily(n + 1)
})
}
}
let grandPa = new Person('张麻子')
let child1 = new Person('张老大')
let child2 = new Person('张老二')
let person11 = new Person('张老大一')
let person12 = new Person('张老大二')
let person21 = new Person('张老二一')
let person22 = new Person('张老二二')
grandPa.addChild(child1)
grandPa.addChild(child2)
child1.addChild(person11)
child1.addChild(person12)
child2.addChild(person21)
child2.addChild(person22)
grandPa.introduceFamily()