一、TypeScript 是什么
在了解 TypeScript (以下简称ts)之前,我们先来说说几个概念:弱类型VS强类型(类型安全的角度);静态类型VS动态类型(类型检查的角度)。
- 弱类型:偏向于不容忍隐式类型转换。
- 强类型:偏向于不容忍隐式类型转换。
- 动态类型:是指在运行期间才去做数据类型检查的语言。在用动态语言编程时,不用给变量指定数据类型,该语言会在你第一次赋值给变量时,在内部将数据类型记录下来。
- 静态类型:与动态类型语言刚好相反,它的数据类型检查发生在在编译阶段,也就是说在写程序时要声明变量的数据类型。
而我们知道js是一门弱类型且动态类型的语言,这使得我们编程的时候更加灵活,但也带来来很多新的问题,我们来看一段代码:
// JavaScript 弱类型产生的问题
// 1. 异常需要等到运行时才能发现
const obj = {}
obj.foo()
setTimeout(() => {
obj.foo()
}, 1000000)
// 2. 函数功能可能发生改变
function sum(a, b) {
return a + b
}
console.log(sum(100, 100))
console.log(sum(100, '100'))
// 3. 对象索引器的错误用法
const obj = {}
obj[true] = 100 // 属性名会自动转换为字符串
console.log(obj['true'])
基于上面的基础,所以我们在js中才要ts,它是 JavaScript 的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。
二、TypeScript 的安装和使用
1.安装 TypeScript
$ npm install -g typescript
2.编译 TypeScript 文件
$ tsc helloworld.ts
# helloworld.ts => helloworld.js
三、TypeScript 基础类型
1. Boolean 类型
let isDone: boolean = false;
// ES5:var isDone = false;
2. Number 类型
let count: number = 10;
// ES5:var count = 10;
3. String 类型
let str: string = 'hello';
// ES5:var str = 'hello';
4. Null 和 Undefined 类型
let u: undefined = undefined;
let n: null = null;
5. Symbol类型
const h: symbol = Symbol();
6. Array 类型
let list: number[] = [1, 2, 3];
// ES5:var list = [1,2,3];
let list: Array<number> = [1, 2, 3]; // Array<number>泛型语法
// ES5:var list = [1,2,3];
7. Enum 类型
//枚举
const enum postStatus {
benagin,
start,
fineshed
}
const obj ={
a:1,
b:postStatus.benagin
}
console.log(obj)
8. Tuple 类型
// 元组(Tuple)
const tuple: [number, string] = [18, 'zce']
const entries: [string, number][] = Object.entries({
foo: 123,
bar: 456
})
const [key, value] = entries[0]
// key => foo, value => 123
9. Void 类型
const e: void = undefined
const e1: void = null
// 声明函数返回值为void
function warnUser(): void {
console.log("This is my warning message");
}
10. Any 类型
let notSure: any = 666;
notSure = "Semlinker";
notSure = false;
四、TypeScript 断言
有时候你会遇到这样的情况,你会比 TypeScript 更了解某个值的详细信息。通常这会发生在你清楚地知道一个实体具有比它现有类型更确切的类型。
通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。类型断言好比其他语言里的类型转换,但是不进行特殊的数据检查和解构。它没有运行时的影响,只是在编译阶段起作用。
类型断言有两种形式:
- “尖括号” 语法
let arr:number[] = [1,2,3,4]
let num = arr.find(i=>i>1)
let add = <number>num + <number>num //react JSX 下不能使用
- as 语法
let arr:number[] = [1,2,3,4]
let num = arr.find(i=>i>1)
let add =( num as number) + ( num as number)//所以推荐写这种
五、联合类型和类型别名
- 联合类型
const sayHello = (name: string | undefined) => {
/* ... */
};
- 类型别名
type Message = string | string[];
let greet = (message: Message) => {
// ...
};
六、TypeScript 接口
在面向对象语言中,接口是一个很重要的概念,它是对行为的抽象,而具体如何行动需要由类去实现。
TypeScript 中的接口是一个非常灵活的概念,除了可用于 对类的一部分行为进行抽象 以外,也常用于对「对象的形状(Shape)」进行描述。
interface Post {
title: string
content: string
}
function printPost (post: Post) {
console.log(post.title)
console.log(post.content)
}
七、TypeScript 泛型
泛型(Generics)是允许同一个函数接受不同类型参数的一种模板。相比于使用 any 类型,使用泛型来创建可复用的组件要更好,因为泛型会保留参数类型。
////泛型极大提高了代码得复用
function fn1<T>(len:number,value:T):T[]{
return Array<T>(len).fill(value)
}
fn1(4,5)
fn1(4,'4')
八、TypeScript 类
1. 类的属性与方法
// 类(Class)
export {} // 确保跟其它示例没有成员冲突
class Person {
//类得属性在使用之前必须在类型当中先注明
name: string // = 'init name'
age: number
private sex: string //私有成员,只能在当前类访问
protected readonly gender: boolean //保护成员 可以在子类访问
constructor (name: string, age: number,sex: string,gender: boolean,) {
this.name = name
this.age = age
this.sex = sex
this.gender = gender
}
sayHi (msg: string): void {
console.log(`I am ${this.name}, ${msg}`)
}
}
2. 类与接口
// 类与接口
export {} // 确保跟其它示例没有成员冲突
interface Eat {
eat (food: string): void
}
interface Run {
run (distance: number): void
}
class Person implements Eat, Run {
eat (food: string): void {
console.log(`优雅的进餐: ${food}`)
}
run (distance: number) {
console.log(`直立行走: ${distance}`)
}
}
class Animal implements Eat, Run {
eat (food: string): void {
console.log(`呼噜呼噜的吃: ${food}`)
}
run (distance: number) {
console.log(`爬行: ${distance}`)
}
}
3. 抽象类
//抽象类,只能被继承,不能被new
abstract class Animal {
eat (food: string): void {
console.log(`呼噜呼噜的吃: ${food}`)
}
abstract run (distance: number): void
}
class Dog extends Animal {
run(distance: number): void {
console.log('四脚爬行', distance)
}
}
const d = new Dog()
d.eat('嗯西马')
d.run(100)