初识TypeScript

  1. 目前typescript已经是前端的一个加分项;
  2. 微软发明的TypeScript,JavaScript是网景公司发明的,TypeScript主要是用于解决JS的一些错误;
  3. TypeScript兼容大部分JS代码,可以把TypeScript当JavaScript写。

安装与调试


配置 npm 淘宝源

npm config set registry https://registry.npm.taobao.org/

如果后悔了,想撤销淘宝源就运行 npm config delete registry

安装

npm install typescript@2.9.2 -g
现在 TypeScript 已经升级到 3 了,上面这一行你也可以写成 typescript@3
ts-node是让node支持ts,原本node是可以直接运行JS的,node不能直接运行TS,需要通过ts-node
npm install ts-node@7.0.0 -g

注意记下 ts-node 安装后的可执行文件路径,后面要用的。
[图片上传失败...(image-5e288f-1617845214622)]

image.png

复制一下路径

调试

  1. 下载 vscode

    • 按 ctrl+K ctrl+S
    • 将格式化文件的快捷键绑定到自己喜欢的按键(我用的是 ctrl+L)
  2. 创建文件夹 tsdemo

  3. 用 vscode 打开 tsdemo 目录:将 tsdemo 目录拖曳进 vscode 即可。

  4. 创建 tsdemo/1.ts 作为我们的第一个 TS 文件

  5. 在文件里写一句 console.log(1) 保存

  6. Windows 用户注意了,这里需要单独运行一些命令(Linux 用户和 macOS 用户不用执行)

    • npm init -y
    • npm i -D ts-node typescript
  7. 创建 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"
             }
         ]
     }
    
  8. 打开 tsdemo/1.js,找到调试选项,选择 ts-node,然后点击调试


    image.png
  9. 然后你就可以看到 console.log(1) 的输入结果了(请确保你选中的是 tsdemo/1.ts)


    image.png

参考文章:https://segmentfault.com/a/1190000011935122

开始学习

  1. 前置知识
    • 你要对 npm 比较熟悉
    • 你要对命令行比较熟悉
    • 你要对 ES 6 比较熟悉
    • 你要对 class 比较熟悉
  2. 学习一下官方的五分钟教程
  3. 刻意练习
    • 大概浏览一下文档
    • 一些简单的计算
    • 一些简单的应用
    • 边练习边查文档
enum Gender {
  Male,
  Female
}
interface Person {
  gender: Gender;
}

function merry(a: Person, b: Person): [Person, Person] {
  if (a.gender !== b.gender) {
    return [a, b];
  } else {
    throw new Error('性别相同不能结婚');
  }
}

let a = { gender: Gender.Male };
let b = { gender: Gender.Male };
console.log(merry(a, b));

function selectSort(a: number[]): number[]{
  for(let i =0;i<a.length-1;i++){
    let minIndex = i;
    for(let j = i+1; j<a.length; j++){
      if(a[j]<a[minIndex]){
        minIndex = j
      }
    }
    let temp = a[minIndex]
    a[minIndex] = a[i]
    a[i] = temp
  }
  return a
}

let b = selectSort([100,4,50,1,3])
console.log(b)

function add(a: string, b: string): string;
function add(a: number, b: number): number;
function add(a: any, b: any): any {
  return a + b;
}

console.log(add('frank',1))

function min(a:number, b:number): number {
  if (a < b) {
    return a;
  } else {
    return b;
  }
}

var c = min(1, 2);
console.log(c);

官网学习TypeScript


  1. 官网:https://www.typescriptlang.org/

  2. 什么是tsc?

    • 浏览器可以直接运行JS
    • 浏览器不能直接运行TS
    • 我们需要将TS转换成JS,才能运行在浏览器上
    • tsc(TypeScript Compiler)就是可以将TS转换成JS
    • 运行greeter.ts之后就会出现一个新的greeter.js文件
    • 目前我们看到的JS和TS都是一样的
  3. TS中有JS没有的,我们可以直接指定person的类型,在参数后面加冒号,再加一个类型,可以指定类型


    image.png
  4. 我们发现编译后的js并没有发生变化


    image.png
  5. 我们现在尝试往里面放数组,看看有没有变化?我们发现编译会报错


    image.png
  6. 通过TSC将TS转成JS需要做以下的事情

    1. 类型检查
      • 这也是TypeScript最大的意义

      • 不使用typescript就需要原生JS做类型检测

        • image.png
      • 但是等到使用的时候才会报错,用户会感觉到。而TypeScript是可以在编译的时候直接报错,用户看不到的

      • 目前是有string和undefined可以不报错

  7. 接口

    • 接口实际上规定了数据结构
    • image.png
    • 接口不支持函数
  8. 类:

    • 类中加了public,会帮你把后面的变量变成对象的一个属性
    • image.png
    • 这样使用new方法创建的user就具有Person里面的属性,可以转成Person
    • 在构造函数的参数上使用public等同于创建了同名的成员变量
    • 当我们更改一下这个代码,使用一个Person没有的属性但是Student有的属性,会报错的。


      image.png

带着问题看文档


  1. 学习TS的几个建议
    • CRM
    • 单纯学TS,不要又着手其他技术
    • 对于新技术,不要看书,看文档或博客
  2. 在看完技术文档之后。不需要全部明白,全部熟悉。直接写代码,带着问题去找文档就好了
  3. 重载可以支持多种形式的类型输入

我们通过解决一个小问题来学习TypeScript

最简单的命令行程序


1.ts

#!/usr/bin/env ts-node
console.log('hello world')

然后给该文件添加执行权限:`chmod +x ./1.ts (Windows 用户不需要做这个,直接在 Git Bash 输入 ./1.ts 即可运行)执行 ./1.ts就会看到 hello world
这样命令行可以直接执行文件了

接受命令行参数


2.ts

#!/usr/bin/env ts-node
console.log(process.argv)

process.argv可以获取用户输入在命令行的内容

  1. 我们在运行./1.ts的时候,发现报了一个错误


    image.png
  2. 找不到process,那么我们就根据建议运行npm i @types/node,这个的意思好像是node的类型定义。

3.安装结束再运行就发现可以了,可以将命令行的内容输出

image.png
  1. 目前我们的程序可以读取用户传给我们的额外的参数

如果没有配置好 TS,那么运行 ./2.ts 上面代码会出现如下报错:

/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)

报错说得很清楚,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
# 再次运行 ./2.ts
> ./2.ts
[ 'node', '/Users/frank/TypeScript/tsdemo/2.ts' ]

就可以了。

那么 @types/node 到底定义了什么呢?打开 ./node_modules/@types/node/index.d.ts 搜索 Process 就能看到 process 的定义了:


    export interface Process extends EventEmitter {
        stdout: WriteStream;
        stderr: WriteStream;
        stdin: ReadStream;
        openStdin(): Socket;
        argv: string[];
        argv0: string;
        execArgv: string[];
        execPath: string;
        ...

另一个很悬疑的问题:你怎么知道要运行 npm install @types/node
对啊,我怎么知道。新人根本不可能知道啊。

过程:

  1. 复制 error TS2304: Cannot find name 'process'. 到 Google
  2. 找到 Stackoverflow 上的一篇问答
  3. 得知要安装 Typings,于是点开他给的链接
  4. 看到页面上方显示 Typings is deprecated in favor of NPM @types
  5. 得知 Typings 已经被弃用了,但是这货不告诉我新版在哪
  6. 猜测新版是 @types/node (纯经验)
  7. 运行 npm install @types/node 然后运行 ./2.ts 发现成功
  8. 去 Stackoverflow 回复一下,以防别人也遇到不知道新版名称
  9. 回复的时候发现已经有人回复了 with typescript 2, its now npm i -D @types/node
  10. 发现他用了 -D 选项但是我没有使用,根据我对 npm 的了解,加不加 -D 都行,加上更好一点。

VSCode 内置终端


点开 VSCode 的内置终端就可以运行命令行很方便。
不过有的时候会遇到奇怪的问题,遇到问题你就改用 Git Bash 即可。

四则运算


加法 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 变成数字,我们需要改代码:

  1. 我们在VSCODE里面可以按住control,查看变量的定义,可以看到,都在一个global.d.ts文件中,相当重要

  2. 看到process的参数定义全是设定成了string
    image.png
  3. 改成number试试看?好像没成功。哈哈哈

  4. return只能在函数体里面使用,没有函数体怎么让代码中断呢?使用process.exit()
    image.png
  5. 程序员约定正常退出的时候在process.exit(0),添个0。不是正常退出的,添个不是0的就好了;这种想法就像成功只有一种可能,不成功却有千百种
    image.png
  6. 我们现在实现一个族谱,里面的类需要一个children的数组,这个数组我们可以规定其类型,但是需要进行赋值,否则就会出错,没有赋值,即便是指定了类型,还是会作为undefined,因此必须在刚开始就赋值
    image.png
  7. 有一个API叫做repeat。可以重复打印string
    image.png
    #!/usr/bin/env ts-node
    class Person {
        public children: Person[] = []
        constructor(public name: string) {
        }
        // : void代表什么也不反悔
        addChild(child: Person): void {
            this.children.push(child)
        }
        introduceFamily(n: number): void {
            let prefix = '----'.repeat(n)
            console.log(prefix + 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(0)
    
#!/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 成功!
但是

# ./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('输入不合法');
  return; // 有问题
}

console.log(a + b);

return 这句话有问题,因为不能在顶级作用域运行 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
输入不合法

接下来创建 minus.ts、multiply.ts 和 devide.ts,分别对应减法、乘法和除法。

族谱


#!/usr/bin/env ts-node
function createTabs(n: number): string {
  return '----'.repeat(n);
}
class Person {
  public children: Person[] = [];
  constructor(public name) {}
  addChild(child: Person): void {
    this.children.push(child);
  }
  introduceFamily(n?: number): void {
    n = n || 0;
    console.log(`${createTabs(n)}${this.name}`);
    this.children.forEach(person => {
      person.introduceFamily(n + 1);
    });
  }
}

const grandPa = new Person('王麻子');
const person1 = new Person('王大锤');
const person2 = new Person('王者');
const child11 = new Person('王毛');
const child12 = new Person('王水');
const child21 = new Person('王荣耀');
const child22 = new Person('王农药');

grandPa.addChild(person1);
grandPa.addChild(person2);

person1.addChild(child11);
person1.addChild(child12);
person2.addChild(child21);
person2.addChild(child22);

grandPa.introduceFamily();

王麻子
----王大锤
--------王毛
--------王水
----王者
--------王荣耀
--------王农药

知识点:

  1. n?: number
  2. class
  3. repeart

如何自学


  1. 不要怕
  2. 不要妄图系统学习
  3. 有目的去学(带着任务)/无目的(看书X10,不推荐)

如何让网页直接使用TS?


以制作一个可以拖拽的div为例

  1. 新创建一个ts-demo,里面有一个index.html,以及index.html以及main.ts,其中index.html直接引用这个TS文件
    image.png
  2. 我们首先在TS中写的是纯JS文件,这个是可以在网页上运行的,但是一旦这个文件中有不是JS类型的语法,就会出错

  3. 这时候我们需要在中断运行一下npx parcel index.html

  4. 运行结束之后,目录中多出来一些文件,这个是一个打包工具,会自动将其TS转译成JS文件
    npx parcel index.html

  5. 我们在写这个demo的时候,发现对于string和number的转换需要格外注意,一旦有问题,就会报错。但是如果一个top的值为auto的话,就会出现报错。TS不报错也不代表没有问题,比如当top为auto的时候不报错,但是代码无法正常执行
    image.png
  6. 我们需要使用TS的严格模式,我们需要有一个配置文件tsconfig.json。从网上直接搜索一个例子下来就好了,删除多余的参数,添加一个严格的空值检测
    image.png
  7. 报错的时候添加一个!就会实现消除报错,即指明不会为空

  8. TS的高明之处在于类型自动推导,也可以显式推导

TS可以显式声明类型


  1. TS的原理就是根据原先就存在的类型或者赋值,推测新的类型
  2. 可以通过显式指定类型进行指定类型,也可以通过赋值隐式指定类型
var div: HTMLDivElement = document.createElement('div')
div.style.border = '1px solid red'
div.style.height = '100px'
div.style.width = '100px'
div.id = 'demo'
console.log(div)
document.body.appendChild(div)
var x: boolean = false;
var position: [number, number] = [0, 0]
div.onmousedown = (e: MouseEvent) => {
    x = true
    position = [e.clientX, e.clientY]
}
document.onmousemove = (e) => {
    if (x === true) {
        var deltaX = e.clientX - position[0]
        var deltaY = e.clientY - position[1]
        // 加!是告诉JS这个是不会为空的值
        var top = parseInt(div.style.top!) || 0
        var left = parseInt(div.style.left!) || 0
        div.style.top = top + deltaY + 'px'
        div.style.left = left + deltaX + 'px'
        position = [e.clientX, e.clientY]
    }
}
document.onmouseup = (e) => {
    x = false
}

TS编译成JS并部署


  1. 我们现在拥有的是ts文件,index.html以及css文件,直接上传到git上面是无法运行的,因为git上面没有parcel工具,只能运行JS。我们需要在下面将其转换成js然后上传

  2. 将目录文件中dist目录中的文件全部删除
    image.png
  3. 然后在终端运行:npx parcel build index.html,运行结束会在dist下面有多出几个文件
    image.png
  4. 我们上传上去git的index.html引用有问题,重新上传,使用npx parcel build --public-url ./ index.html,使用相对路径。可以成功运行;这种build是一种编译,即将一种语言变成另一种语言
    image.png

VSCode技巧


  • 随时格式化自己的代码
    • 可以开启 Format On Save
    • 可以开启 Auto Save
  • 使用parcel自动刷新页面
    • parcel有一个bug,如果没有js就不刷新
    • 所有软件都有bug吗,切记
    • 所以我推荐新人学习的时候尽量少用工具,只用必要的工具,这个parcel就没什么必要,还不如自己刷新
    • 如果你用parcel遇到问题,请直接放弃,不要浪费时间研究它,入门要紧
  • TS代码后面与分号,但是VSCode不会自动给你加分号。添插件就好

了解http协议和file协议的区别


  1. npx http-server . -c-1
  2. 点代表在当前目录运行,-c-1是缓存负1秒
  3. 使用这个方法,相当于在本地开了一个服务器。浏览器可以访问地址

总结


  • 想要掌握TS
    • 看书是辅助
    • 做项目是最快路径
    • 做出一个能用的东西,让自己活得成就感
    • 让成就感驱动你做更多的东西
  • 想要系统掌握TS
    • 先掌握JS
    • 然后学会类型声明
  • 所有能用JS实现的最终都会用TS实现
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容