深入浅出 TypeScript | 青训营笔记

97 阅读7分钟

TypeScript 是 JavaScript 的超集,包含 ES5、6、7等,(有强大的类型系统)

  • 新增了类型系统和完整的面向对象语法
  • 使用 TS 编写的项目更健硕,且更容易扩展和维护,通俗点就是规范
  • TS代码需要通过编译器编译为JS,然后再交由JS解析器执行。
  • TS完全兼容JS,换言之,任何的JS代码都可以直接当成JS使用。
  • 相较于JS而言,TS拥有了静态类型,更加严格的语法,更强大的功能;TS可以在代码执行前就完成代码的检查,减小了运行时异常的出现的几率;TS代码可以编译为任意版本的JS代码,可有效解决不同JS运行环境的兼容问题;同样的功能,TS的代码量要大于JS,但由于TS的代码结构更加清晰,变量类型更加明确,在后期代码的维护中TS却远远胜于JS。

安装

  • 使用npm全局安装typescript npm i -g typescript
  • 创建一个ts文件,使用tsc对ts文件进行编译,执行命令:tsc xxx.ts

类型

基本类型

  • boolean
  • number
  • string
  • array
  • 元组类型(tuple)
  • 枚举类型(enum)
  • 任意类型(any)
  • null
  • undefined
  • object
  • void
  • never

高级类型

  • union 组合类型
  • Nullable 可空类型
  • Literal 预定义类型

自动类型判断

  • TS拥有自动的类型判断机制
  • 当对变量的声明和赋值是同时进行的,TS编译器会自动判断变量的类型
  • 所以如果变量的声明和赋值是同时进行的,可以省略掉类型声明

**

// 声明完变量直接进行赋值
// let c: boolean = false;

// 如果变量的声明和赋值是同时进行的,TS可以自动对变量进行类型检测
// c只能是布尔类型的值
let c = false;
c = true;

类型声明

TS中的类型判断一般用于函数的参数和函数的返回值的情况较多,因为JS中的函数是不考虑参数的类型和个数的

**

// JS中的函数是不考虑参数的类型和个数的
// function sum(a, b){
//     return a + b;
// }

// console.log(sum(123, 456)); // 579
// console.log(sum(123, "456")); // "123456"

function sum(a: number, b: number): number{
    return a + b;
}

let result = sum(123, 456);

类型断言(类型适配)

类型断言,可以用来告诉编辑器变量的实际类型,使用类型断言一定要对当前对象的类型有百分之百的信心,否则会出现严重的错误

**

/*
* 语法:
*   变量 as 类型
*   <类型>变量
* */
s = e as string;
s = <string>e;

let message: any
message = "abc"
message.endsWith("c") //调用endWith方法的时候,编辑器并不会出现提示,因为此时message还是any类型,即使已经用一个string 类型赋值了 这个时候可以使用类型断言

// 法一
let ddd = (<string>message).endsWith("c")
// 法二
let ddd2 = (message as string).endsWith("c")

元组类型(tuple) 固定长度的数组

**

// 该数组 第一个元素是number类型 第二个元素是string类型 并且数组长度只能是2位
let arr: [number, string] = [123, "this is ts"]
// arr.push(3) 这边一定要注意元组是固定类型的,是不能够push的,但是这句话编译会通过 平时一定要注意

在声明元组的时候一定要指定类型,如果没有指定类型,其实本质上是一个联合类型数组

**

let p2 = [1, 'haha'] // p2是一个数组 既不固定长度,也不固定数组
p2[0] = "ddd" // 可以让第一位为字符串,也可以让第二位为数字
p2[1] = 1
p2[2] = 5 // 也可以添加第3位

枚举类型

适合结果在多个值之间进行选择

**

enum Gender{
    Male,
    Female
}

let i: {name: string, gender: Gender};
i = {
    name: '孙悟空',
    gender: Gender.Male // 'male'
}

联合类型(限制变量在某几个值之间)

**

let union: string | number
union = 2
union = "haha"

let union2: number | string | boolean | string[]

function merge(n1: number | string, n2: number | string) {
  // 进行简单的类型适配
  if (typeof n1 === "string" || typeof n2 === "string") {
    return n1.toString() + n2.toString() // 这边有点疑问
  } else {
    return n1 + n2
  }
}

let mergeNumber = merge(2, 5)
let mergeString = merge("hello", 1)
console.log(mergeString)

// 明确数据的联合类型 union3 只能是0 1 2 也是字面量类型
let union3: 0 | 1 | 2

字面量类型

**

// 也可以直接使用字面量进行类型声明
// a只能被赋值为10 不能被赋值为其他值 类似常量 很少使用
let a: 10;
a = 10;

// 字面量形式一般用于或的形式较多
// 可以使用 | 来连接多个类型(联合类型)
let b: "male" | "female";
b = "male";
b = "female";

any 类型

**

// any 表示的是任意类型,一个变量设置类型为any后相当于对该变量关闭了TS的类型检测
// 使用TS时,不建议使用any类型
// let d: any; 显示any

// 声明变量如果不指定类型,则TS解析器会自动判断变量的类型为any (隐式的any)
let d;
d = 10;
d = 'hello';
d = true;

unknown 类型

**

// unknown 表示未知类型的值
let e: unknown;
e = 10;
e = "hello";
e = true;

unknown和any的区别在于:any类型的变量可以赋值给任意变量,unknown类型的变量不能直接赋值给其他变量

**

let s:string;
// d的类型是any,它可以赋值给任意变量
s = d;

e = 'hello';
s = e; // 这句话会报错 即使 e 是字符串 因为 e 原本是 unknown 类型
// unknown 实际上就是一个类型安全的any
// unknown类型的变量,不能直接赋值给其他变量,即使赋值的时候两个变量是同一种类型,赋值之前需要进行类型判断
if(typeof e === "string"){
    s = e;
}

void 类型

**

// void 用来表示空,以函数为例,就表示没有返回值的函数
function fn(): void{
    console.log('hahah')
}

never 类型

never 表示永远不会返回结果,连空都没有,一般用于处理报错,函数只要报错,立即执行结束

**

function fn(): never {
  throw new Error("报错了!");
}

object 类型

**

// object表示一个JS对象 因为JS中一切皆对象,所以单纯这样写,没有任何意义
let a: object;
a = {};
a = function () {
};

一般开发中更多的是对对象的属性进行限制,而不是限制它是不是一个对象

**

// {} 用来指定对象中可以包含哪些属性,属性的个数要严格相等
// 语法:{属性名:属性值,属性名:属性值}
// 在属性名后边加上?,表示属性是可选的
let b: {name: string, age?: number};
b = {name: '孙悟空', age: 18};

假设要求 c 这个对象有一个name属性,其他属性不做要求,可有可无

**

// [propName: string]: any 表示任意类型的属性
// propName 是随便起的名字,表示属性名,js中的属性名是字符串类型
let c: {name: string, [propName: string]: any};
c = {name: '猪八戒', age: 18, gender: '男'};

函数结构声明

**

/*
*   设置函数结构的类型声明:
*       语法:(形参:类型, 形参:类型 ...) => 返回值
* */
// d是一个函数,函数参数是number类型,返回值也是number
let d: (a: number ,b: number) => number;
// d = function (n1: string, n2: string): number{
//     return 10;
// }

数组类型声明

2 种定义方式

  • 类型[]
  • Array<类型>

**

/*
*   数组的类型声明:
*       类型[]
*       Array<类型>
* */
// string[] 表示字符串数组
let e: string[];
e = ['a', 'b', 'c'];

// number[] 表示数值数值
let f: number[];
// 和上述表达方式一样,都是表示数值的数组
let g: Array<number>;
g = [1, 2, 3];

// 三种声明数组的方式都可以
let list1: number[] = [1, 2, 3, 4]
let list2: Array<number> = [1, 2, 3, 4]
let list3 = [1, 2, 3, 4]

JS 中声明的数组可以是混合类型 在 TS中同样也可以做到

**

let list1 = [1, "ddd"]
let list2: any[] = [1, "dd", true]

其他

&

**

// &表示同时 表示 j 对象 必须要有 name 和 age 属性
let j: { name: string } & { age: number };
// j = {name: '孙悟空', age: 18};

类型的别名

**

// 类型的别名
type myType = 1 | 2 | 3 | 4 | 5;
let k: myType;
let l: myType;
let m: myType;
k = 2;