- 目前typescript已经是前端的一个加分项;
- 微软发明的TypeScript,JavaScript是网景公司发明的,TypeScript主要是用于解决JS的一些错误;
- 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)]
复制一下路径
调试
-
下载 vscode
- 按 ctrl+K ctrl+S
- 将格式化文件的快捷键绑定到自己喜欢的按键(我用的是 ctrl+L)
创建文件夹 tsdemo
用 vscode 打开 tsdemo 目录:将 tsdemo 目录拖曳进 vscode 即可。
创建 tsdemo/1.ts 作为我们的第一个 TS 文件
在文件里写一句 console.log(1) 保存
-
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" } ] }
-
打开 tsdemo/1.js,找到调试选项,选择 ts-node,然后点击调试
-
然后你就可以看到 console.log(1) 的输入结果了(请确保你选中的是 tsdemo/1.ts)
参考文章:https://segmentfault.com/a/1190000011935122
开始学习
- 前置知识
- 你要对 npm 比较熟悉
- 你要对命令行比较熟悉
- 你要对 ES 6 比较熟悉
- 你要对 class 比较熟悉
- 学习一下官方的五分钟教程
- 刻意练习
- 大概浏览一下文档
- 一些简单的计算
- 一些简单的应用
- 边练习边查文档
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
-
什么是tsc?
- 浏览器可以直接运行JS
- 浏览器不能直接运行TS
- 我们需要将TS转换成JS,才能运行在浏览器上
- tsc(TypeScript Compiler)就是可以将TS转换成JS
- 运行greeter.ts之后就会出现一个新的greeter.js文件
- 目前我们看到的JS和TS都是一样的
-
TS中有JS没有的,我们可以直接指定person的类型,在参数后面加冒号,再加一个类型,可以指定类型
-
我们发现编译后的js并没有发生变化
-
我们现在尝试往里面放数组,看看有没有变化?我们发现编译会报错
-
通过TSC将TS转成JS需要做以下的事情
-
类型检查
这也是TypeScript最大的意义
-
不使用typescript就需要原生JS做类型检测
但是等到使用的时候才会报错,用户会感觉到。而TypeScript是可以在编译的时候直接报错,用户看不到的
目前是有string和undefined可以不报错
-
类型检查
-
接口:
- 接口实际上规定了数据结构
- 接口不支持函数
-
类:
- 类中加了public,会帮你把后面的变量变成对象的一个属性
- 这样使用new方法创建的user就具有Person里面的属性,可以转成Person
- 在构造函数的参数上使用public等同于创建了同名的成员变量
-
当我们更改一下这个代码,使用一个Person没有的属性但是Student有的属性,会报错的。
带着问题看文档
- 学习TS的几个建议
- CRM
- 单纯学TS,不要又着手其他技术
- 对于新技术,不要看书,看文档或博客
- 在看完技术文档之后。不需要全部明白,全部熟悉。直接写代码,带着问题去找文档就好了
- 重载可以支持多种形式的类型输入
我们通过解决一个小问题来学习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.ts的时候,发现报了一个错误
找不到process,那么我们就根据建议运行npm i @types/node,这个的意思好像是node的类型定义。
3.安装结束再运行就发现可以了,可以将命令行的内容输出
- 目前我们的程序可以读取用户传给我们的额外的参数
如果没有配置好 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
对啊,我怎么知道。新人根本不可能知道啊。
过程:
- 复制 error TS2304: Cannot find name 'process'. 到 Google
- 找到 Stackoverflow 上的一篇问答
- 得知要安装 Typings,于是点开他给的链接
- 看到页面上方显示 Typings is deprecated in favor of NPM @types
- 得知 Typings 已经被弃用了,但是这货不告诉我新版在哪
- 猜测新版是 @types/node (纯经验)
- 运行 npm install @types/node 然后运行 ./2.ts 发现成功
- 去 Stackoverflow 回复一下,以防别人也遇到不知道新版名称
- 回复的时候发现已经有人回复了 with typescript 2, its now npm i -D @types/node
- 发现他用了 -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 变成数字,我们需要改代码:
我们在VSCODE里面可以按住control,查看变量的定义,可以看到,都在一个global.d.ts文件中,相当重要
-
看到process的参数定义全是设定成了string
改成number试试看?好像没成功。哈哈哈
-
return只能在函数体里面使用,没有函数体怎么让代码中断呢?使用process.exit()
-
程序员约定正常退出的时候在process.exit(0),添个0。不是正常退出的,添个不是0的就好了;这种想法就像成功只有一种可能,不成功却有千百种
-
我们现在实现一个族谱,里面的类需要一个children的数组,这个数组我们可以规定其类型,但是需要进行赋值,否则就会出错,没有赋值,即便是指定了类型,还是会作为undefined,因此必须在刚开始就赋值
-
有一个API叫做repeat。可以重复打印string
#!/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();
王麻子
----王大锤
--------王毛
--------王水
----王者
--------王荣耀
--------王农药
知识点:
- n?: number
- class
- repeart
如何自学
- 不要怕
- 不要妄图系统学习
- 有目的去学(带着任务)/无目的(看书X10,不推荐)
如何让网页直接使用TS?
以制作一个可以拖拽的div为例
-
新创建一个ts-demo,里面有一个index.html,以及index.html以及main.ts,其中index.html直接引用这个TS文件
我们首先在TS中写的是纯JS文件,这个是可以在网页上运行的,但是一旦这个文件中有不是JS类型的语法,就会出错
这时候我们需要在中断运行一下npx parcel index.html
运行结束之后,目录中多出来一些文件,这个是一个打包工具,会自动将其TS转译成JS文件
npx parcel index.html-
我们在写这个demo的时候,发现对于string和number的转换需要格外注意,一旦有问题,就会报错。但是如果一个top的值为auto的话,就会出现报错。TS不报错也不代表没有问题,比如当top为auto的时候不报错,但是代码无法正常执行
-
我们需要使用TS的严格模式,我们需要有一个配置文件tsconfig.json。从网上直接搜索一个例子下来就好了,删除多余的参数,添加一个严格的空值检测
报错的时候添加一个!就会实现消除报错,即指明不会为空
TS的高明之处在于类型自动推导,也可以显式推导
TS可以显式声明类型
- TS的原理就是根据原先就存在的类型或者赋值,推测新的类型
- 可以通过显式指定类型进行指定类型,也可以通过赋值隐式指定类型
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并部署
我们现在拥有的是ts文件,index.html以及css文件,直接上传到git上面是无法运行的,因为git上面没有parcel工具,只能运行JS。我们需要在下面将其转换成js然后上传
-
将目录文件中dist目录中的文件全部删除
-
然后在终端运行:npx parcel build index.html,运行结束会在dist下面有多出几个文件
-
我们上传上去git的index.html引用有问题,重新上传,使用npx parcel build --public-url ./ index.html,使用相对路径。可以成功运行;这种build是一种编译,即将一种语言变成另一种语言
VSCode技巧
- 随时格式化自己的代码
- 可以开启 Format On Save
- 可以开启 Auto Save
- 使用parcel自动刷新页面
- parcel有一个bug,如果没有js就不刷新
- 所有软件都有bug吗,切记
- 所以我推荐新人学习的时候尽量少用工具,只用必要的工具,这个parcel就没什么必要,还不如自己刷新
- 如果你用parcel遇到问题,请直接放弃,不要浪费时间研究它,入门要紧
- TS代码后面与分号,但是VSCode不会自动给你加分号。添插件就好
了解http协议和file协议的区别
- npx http-server . -c-1
- 点代表在当前目录运行,-c-1是缓存负1秒
- 使用这个方法,相当于在本地开了一个服务器。浏览器可以访问地址
总结
- 想要掌握TS
- 看书是辅助
- 做项目是最快路径
- 做出一个能用的东西,让自己活得成就感
- 让成就感驱动你做更多的东西
- 想要系统掌握TS
- 先掌握JS
- 然后学会类型声明
- 所有能用JS实现的最终都会用TS实现