用ts开发命令行程序

2019-08-18  本文已影响0人  sweetBoy_9126
最简单的命令行程序
#!/usr/bin/env ts-node
console.log('hello world')

然后给该文件添加执行权限:`chmod +x ./1.ts (Windows 用户不需要做这个,直接在 Git Bash 输入 ./1.ts 即可运行)

执行 ./1.ts

就会看到 hello world

接受命令行参数
#!/usr/bin/env ts-node
console.log(process.argv)

process.argv可以打印出你命令行输入的命令和参数,比如你输入
./1.ts xxx
会得到下面的

[ 'node',
  '/Users/mac/Desktop/study/typeScript/tsdemo/1.ts',
  'xxx' ]

第一个值是你的环境,第二个是你当前文件的路径,第三个包括之后的都是你输入的参数

但是实际上我们直接运行./1.ts xxx会报错

/usr/local/lib/node_modules/ts-node/src/index.ts:261
    return new TSError(diagnosticText, diagnosticCodes)
           ^
TSError: ⨯ Unable to compile TypeScript:
1.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 (internal/modules/cjs/loader.js:787:10)
    at Object.require.extensions.(anonymous function) [as .ts] (/usr/local/lib/node_modules/ts-node/src/index.ts:442:12)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:829:12)

报错说得很清楚,2.ts(2,13): error TS2304: Cannot find name 'process'.找不到 process。

实际上这是 Node.js 的全局变量,不可能找不到。

这就是 TS 的厉害之处:如果你不告诉我 process 是什么,我就不允许你用 process。

那么如何告诉 TS process 是什么呢?

方法如下:

初始化项目的 package.json

npm init -y

安装 node 相关的类型定义

npm install @types/node

再次运行 ./1.ts xxx

./1.ts xxx
[ 'node', '/Users/frank/TypeScript/tsdemo/2.ts', 'xxx' ]
就可以了。

使用ts做加法

add.ts(记得添加可执行权限,Windows 用户不需要加)

#!/usr/bin/env ts-node
const a = process.argv[2];
const b = process.argv[3];

console.log(a + b);
# ./add.ts 1 2
12

1 + 2 居然等于 12,这计算器想个傻子一样。

这是因为目前 a b 的类型是 Any,然后参数 1 2 其实是字符串,所以 a b 也是字符串 1 2 。

为了将 a b 变成数字,我们需要改代码:

#!/usr/bin/env ts-node
const a: number = parseInt(process.argv[2]);
const b: number = parseInt(process.argv[3]);

console.log(a + b);
# ./add.ts 1 2
3

1 + 2 = 3 成功!

但是如果我们某一个参数我们传进去的不是数字,那么parseInt会将它转成NaN,这也不是我们想要的,比如下面

# ./add.ts 1 s
NaN

改代码

#!/usr/bin/env ts-node
const a: number = parseInt(process.argv[2]);
const b: number = parseInt(process.argv[3]);

if (Number.isNaN(a) || Number.isNaN(b)) {
  console.log('输入不合法');
}

console.log(a + b);

报错如下:

/usr/local/lib/node_modules/ts-node/src/index.ts:261
    return new TSError(diagnosticText, diagnosticCodes)
           ^
TSError: ⨯ Unable to compile TypeScript:
add.ts(5,12): error TS2339: Property 'isNaN' does not exist on type 'NumberConstructor'.
add.ts(5,31): error TS2339: Property 'isNaN' does not exist on type 'NumberConstructor'.

    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 (internal/modules/cjs/loader.js:787:10)
    at Object.require.extensions.(anonymous function) [as .ts] (/usr/local/lib/node_modules/ts-node/src/index.ts:442:12)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:829:12)

原因:ts本身不支持es6的语法,解决办法:添加一个tsconfig.json文件

{
    "compilerOptions": {
        "lib": ["es2015"]
    }
}

再次运行

# ./add.ts 1 s
输入不合法
NaN

问题:我们如果不满足条件的情况下只希望打印出‘输入不合法’,而不希望继续执行a+b,可我们不能直接在if语句里写return
解决办法:如果我们需要退出程序,只能使用 process.exit(N),其中的 N 是返回值。
成功的情况下返回值里写0,失败里面写非0的数字

#!/usr/bin/env ts-node
const a: number = parseInt(process.argv[2]);
const b: number = parseInt(process.argv[3]);

if (Number.isNaN(a) || Number.isNaN(b)) {
  console.log('输入不合法');
  process.exit(2);
}

console.log(a + b);
process.exit(0);
# ./add.ts 1 s
输入不合法
族谱
class Person {
    // 默认是一个空数组
    children: Person[] = [];
    constructor(public name) {}
    // 没有返回值就写:void
    appenChild(child: Person): void {
      this.children.push(child);
    }
    introduceFamily(): void {
     console.log(this.name)
      this.children.forEach(child => {
        child.introduceFamily();
      });
    }
  }
let grandPa = new Person('王麻子')
let child1 = new Person('王子')
let child2 = new Person('王大锤')
let person11 = new Person('王毛')
let person12 = new Person('王水')
let person21 = new Person('王毛2')
let person22 = new Person('王水2')

grandPa.appenChild(child1)
grandPa.appenChild(child2)

child1.appenChild(person11)
child1.appenChild(person12)

grandPa.introduceFamily()


# ./x.ts
王麻子
王子
王毛
王水
王大锤
王毛2
王水2

注意:*TS 可以自定义类型,所有class和interface都是类型,所以我们上面可以指定类型为Person

上面的代码层级结构看上去不会很明显,为了更好的体现出来,我们给层级下面加---,每深入一级就多加三根杠

class Person {
  children: Person[] = [];
  constructor(public name) { }
  appenChild(child: Person): void {
    this.children.push(child);
  }
  introduceFamily(n?: number): void {
    let n1 = n || 1
    let profix = ('---').repeat(n1 - 1)
    console.log(profix + this.name)
    this.children.forEach(child => {
      child.introduceFamily(n1 + 1);
    });
  }
}
grandPa.appenChild(child1)
grandPa.appenChild(child2)

child1.appenChild(person11)
child1.appenChild(person12)

child2.appenChild(person21)
child2.appenChild(person22)

grandPa.introduceFamily()

# ./x.ts
王麻子
---王子
------王毛
------王水
---王大锤
------王毛2
------王水2

上面的n? : number 意思是n是可选参数,可以传也可以不传

上一篇 下一篇

猜你喜欢

热点阅读