什么是TypeScript?
- TypeScript是JavaScript的超集,Typing代表强类型语言,是在JS的基础上加了一层类型定义
- TypeScript会做类型推演和类型匹配
- TypeScript的类型检查,在编译阶段就能发现错误,极大地避免了低级错误,规范了我们的代码
- TypeScript支持JavaScript最新特性(ES6/7) ```typescript var button = document.getElementById(“query”) var num1 = document.getElementById(“num1”) as HTMLInputElement; var num1 = document.getElementById(“num2”) as HTMLInputElement;
function add(num1: number, num2: number) { return num1 + num2; }
button.addEventListener(“click”, () => { console.log(add(+num1.value, +num2.value)); });
<a name="Ei9C4"></a>
### TypeScript开发环境搭建
[typescript官方文档](https://www.typescriptlang.org/docs/handbook/typescript-tooling-in-5-minutes.html)
1. 安装NodeJS
2. 全局安装typescript
```bash
npm install -g typescript
# 或者
yarn global add typescript
- 安装VSCode,`ctrl+``调出终端
安装好后查看版本
node -v
tsc -v
编译ts文件, 生成js文件
tsc main.ts
运行js文件
node main.js
JS的版本
ES6 = ES2015
ES2016=ES7
ES2017=ES8
用npm管理项目
使用命令npm init初始化项目,会生成package.json文件
安装lite-server
npm install --save-dev lite-server
#或者
yarn add --dev lite-server
在package.json的scripts中添加start命令
"scripts": {
"start": "lite-server",
"test": "echo \"Error: no test specified\" && exit 1"
},
新建index.html文件,在其中引入main.js文件
使用命令**npm start**
启动项目
TypeScript
boolean/number/string
let a = true // 自动推断类型
let isTrue: boolean // 手动指定类型
const total: number = 0;
let firstName: string = `Alex`
数组Array和元组Tuple
// 数组
let list1:number[] = [1,2,3,4]
let list2:Array<number> = [1,2,3,4]
let list3 = [1,2,3,4]
let list4: any[] = [1, 'hello', true]
// 元组
let person1: [number, string] = [1, "alex"]
person1.push("xxx") // bug
- 元组是固定长度(2位),固定类型的特殊数组,是TypeScript新增的,JS没有,在声明时必须指定类型
- Typescript中的元组还不完善,使用push可以突破元组的限制,无限添加元素
联合(Union)与字面量(Literal)
type A = string | number | boolean
type B = 1 | 'hello' | true
枚举类型(Enum)
```typescript enum Color { red, green, blue, }
console.log(Color.green) // 输出为1, 索引从0开始
enum Color2 { red = ‘red’, green = ‘green’, blue = 1, }
console.log(Color2.green) // 输出为green
Object.values(Color2) // 获取值
<a name="qE5AF"></a>
### Any 与 unknown
any是任意类型,只有运行时才能发现错误,any适合偷懒的时候使用<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/1753813/1633316601810-c3b0fc99-619a-4b59-a409-dcdf20a9949c.png#clientId=uefcf0fa0-15c0-4&from=paste&height=99&id=uf2d83ee4&margin=%5Bobject%20Object%5D&name=image.png&originHeight=126&originWidth=452&originalType=binary&ratio=1&size=8427&status=done&style=none&taskId=uab8366f3-3278-4a87-abae-0e6f6c5b9c7&width=355)<br />unknown保证了类型安全,必须做类型判断才能使用<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/1753813/1633316695319-927774b2-1a8b-438e-b365-71b74b536946.png#clientId=uefcf0fa0-15c0-4&from=paste&height=156&id=u19f92629&margin=%5Bobject%20Object%5D&name=image.png&originHeight=225&originWidth=511&originalType=binary&ratio=1&size=15826&status=done&style=none&taskId=ua761a432-8e01-4cb0-a45e-af65e0bf8f1&width=354.5)
<a name="VJHlZ"></a>
### void, undefined, never
void指返回值本身不存在
```typescript
function printResult(): void {
console.log("lalala")
}
undefined指返回值存在,但未初始化
function printResult(): undefined {
console.log("lalala")
return
}
never指函数未执行完成:抛出异常或死循环了
function printResult(): never {
throw 'error'
console.log('lalala')
}
类型适配(类型断言) type assertion
let msg:any = 'abc'
// 2种方式使用类型适配
let b = (<string>msg).endsWith('c')
let c = (msg as string).endsWith('c')
使用类型断言必须清除地知道变量的类型,否则容易引发严重的错误
函数
可选参数或者默认值都要放在参数末尾
const fn = (a: string, b: number = 1, c?:string) => {
console.log(a, b, c)
}
class
interface IPoint {
x: number
y: number
drawPoint: () => void
getDistance: (p: IPoint) => number
}
class Point implements IPoint {
x: number
y: number
constructor(x: number, y: number) {
this.x = x
this.y = y
}
drawPoint() {
console.log('x: ', this.x, 'y: ', this.y)
}
getDistance(p: IPoint) {
return Math.pow(p.x - this.x, 2) + Math.pow(p.y - this.y, 2)
}
}
const aPoint = new Point(1, 2)
const bPoint = new Point(3, 4)
aPoint.drawPoint()
console.log(aPoint.getDistance(bPoint))
访问修饰符 Access Modifier
默认是public, 不需要特别指明
如果在constructor的参数中使用访问修饰符,则不需要再额外声明和赋值
class Point implements IPoint {
// x: number
// y: number
constructor(public x: number, public y: number) {
// this.x = x
// this.y = y
}
// ...
}
private禁止从外部访问, 私有变量一般前面加下划线
protected禁止从外部访问,但允许子类访问,
interface中都只能是public的
访问私有变量使用getter和setter
class Point implements IPoint {
// x: number
// y: number
constructor(private _x: number, private _y: number) {
// this.x = x
// this.y = y
}
drawPoint() {
console.log('x: ', this._x, 'y: ', this._y)
}
getDistance(p: IPoint) {
return Math.pow(p.x - this._x, 2) + Math.pow(p.y - this._y, 2)
}
set x(value: number) {
if(value < 0)
throw new Error('x必须大于0')
this._x = value
}
get x() {
return this._x
}
set y(value: number) {
if(value < 0)
throw new Error('y必须大于0')
this._y = value
}
get y() {
return this._y
}
}
编译时报错
在命令中指定target
tsc -t es5 main.ts
泛型
泛型,允许我们在定义的时候不具体指定类型,而是泛泛地说一种类型,并在函数调用的时候再指定具体的参数类型。
上面代码的意思是对 T 进行处理,是返回一个 T 的子集
简单来说,将类型看成值,然后对类型进行编程,这就是泛型的基本思想。泛型类似我们平时使用的函数,只不过其是作用在类型上,思想上和我们平时使用的函数并没有什么太多不同,泛型产生的具体类型也支持类型的操作。
function id<T, U>(arg1: T, arg2: U): T {
return arg1;
}