TypeScript 是 javaScript 的类型的超集,它可以编译成纯 javaScript。编译出来的 javaScript 可以运行在任何浏览器上。TypeScript 编译工具可以运行在任何服务器和任何系统上。TypeScript 是开源的。

首先声明一点:TypeScript 中变量是强类型的。

TypeScript 中为了使编写的代码更加规范,更有利于维护,增加了类型校验,就是在定义变量的时候要指定变量类型

TypeScript 中的数据类型(12 种)有:

  • undefined
  • null: 空类型;
  • Number: 数值类型;
  • String: 字符串类型;
  • Boolean: 布尔类型;
  • Object
  • enum: 枚举类型;
  • any: 任意类型;
  • void: 空类型;
  • Array: 数组类型;
  • Tuple: 元组类型;
  • never 类型

    ts 代码必须指定变量类型。

c82009c10e6ab7cc82416ae7854f3c2c.png

数组(引用类型)

声明数组的方法(两种)

// var arr = [1, 2, 3]; // es5定义数组方式

// ts定义数组,方式1,声明一个数值类型的数组
let arr: number[] = [1, 2, 3];
console.log(arr);
// ts定义数组,方式2,声明一个字符串类型的数组
let arr2: Array<string> = ['2', '3', '4'];
console.log(arr2);
1
2
3
4
5
6
7
8

给数组赋值

  1. 字面量赋值法
  2. 构造函数赋值法
// 字面量赋值法
const arr1: number[] = []; // 定义一个空数组
const arr2: number[] = [1, 2, 3]; // 定义一个只能存放数值类型的数组

const arr3: Array<string> = ['a', 'b'];
const arr4: Array<boolean> = [true, false];
1
2
3
4
5
6

需要注意的是:在 TypeScript 中指定数据类型的数组只能存储同一类型的数组元素。

// 报错,必须存储number类型的数据
const arr: number[] = [1, 2, true];
1
2

在 TypeScript 中使用 Array 这个引用类型来表示数组的,那么每一个数组都是 Array 类型的实例。那么,我们在创建数组的时候也可以使用构造函数来进行赋值。

// 构造函数赋值法
let arr1: number[] = new Array();
let ara2: number[] = new Array(1, 2, 3, 4, 5);
let arr3: Array<string> = new Array('a', 'b', 'c');
let arr4: Array<boolean> = new Array(true, false);
1
2
3
4
5

元组(属于数组的一种)

元组(开发中用的比较少)是一种特殊的数组,可以给数组中的每个索引元素指定数据类型。元祖类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。

// 初始化正确(数组的第一个元素必须是数字,第二个元素必须是字符串,第三个元素必须是布尔值)
const tuple: [number, string, boolean] = [24, 'abc', true];
1
2
// 初始化失败
const tuple: [number, string, boolean] = ['24', 'abc', true];
1
2

如果不遵循为元组预设排序的索引规则,那么 Typescript 会警告: db252b12d505312590f26321c6f0c306.png tuple 第一项应为 number 类型。

字符串(String)

在 TypeScript 中存在两种类型的字符串:

  1. 基本类型字符串:由单引号或者双引号括起来的一串字符串。
  2. 引用类型字符串:用 new 实例化的 String 类型。
const str1: string = '123';
const str2: String = new String('test');
console.log(str1); // '123'
console.log(str2); // [String: 'test']
console.log(str1.length); // 3
console.log(str2.length); // 4
1
2
3
4
5
6

需要说明的是:这两种声明字符串的方法没有什么不同。基本类型的字符串可以直接使用引用类型的属性和方法。

日期对象(引用类型)

不传递任何参数

const d: Date = new Date();
console.log(d); // 2020-02-02T09:50:43.484Z
1
2

传递一个整数

传递一个整数,这个整数代表的是距离 1970-01-01 00:00:00 的毫秒数(具体为什么是这个时间,小伙伴可以自己百度一下)。例如:传入参数为 1000,将创建一个表示 1970-01-01 00:00:01 的日期对象。

我们举个例子,传递一个整数,看一下结果:

const d2: Date = new Date(1000);
const d3: Date = new Date(2000);
console.log(d2); // 1970-01-01T00:00:01.000Z
console.log(d3); // 1970-01-01T00:00:02.000Z
1
2
3
4

传递一个字符串

如果传递一个表示日期的字符串,就会生成相对应的日期对象。字符串的格式常用:yyyy/MM/dd hh:mm:ss,yyyy-MM-dd hh:mm:ss,yyyy-MM-ddThh:mm:ss 等,具体可以参看下面的例子:

const d4: Date = new Date('2020/02/02 05:55:00');
const d5: Date = new Date('2020-02-02 05:55:00');
const d6: Date = new Date('2020-02-02T05:55:00');
console.log(d4); // 2020-02-01T21:55:00.000Z
console.log(d5); // 2020-02-01T21:55:00.000Z
console.log(d6); // 2020-02-01T21:55:00.000Z
1
2
3
4
5
6

传递表示年月日时分秒的变量

let d: Date = new Date(year, month, day, hours, minutes, seconds, ms);
1
  • year:表示年份,4 位数字;
  • month:表示月份,数值是 0(1 月)~11(12 月)之间的整数。
  • day:表示日期。数值是 1~31 之间的整数。
  • hours:表示小时,数值是 0-23 之间的整数。
  • minutes:表示分钟数,数值是 0~59 之间的整数。
  • seconds:表示秒数,数值是 0~59 之间的整数。
  • ms:表示毫秒数,数值是 0~999 之间的整数。

正则表达式

创建正则表达式的两种方法:

  1. 构造函数法
  2. 字面量法

构造函数法

构造函数中可以传一个参数,也可以传递两个参数。一个是字符串描述,另一个是修饰符,比如 g 是全局修饰符,i 是忽略大小写,m 是多行模式。

const reg1: RegExp = new RegExp('testreg');
console.log(reg1); // /testreg
const reg2: RegExp = new RegExp('testreg', 'gi');
console.log(reg2); // /testreg/gi
1
2
3
4

字面量法

其实构造函数的方法我个人用的是比较少的,我都会使用字面量法来声明正则表达式。

let reg3: RegExp = /testreg/;
let reg4: RegExp = /testreg/gi;
1
2

RegExp 中的常用方法

RegExp 对象包含两个方法:test 和 exec,功能基本相似,用于测试字符串匹配。

  • test(string):在字符串中查找是否存在指定的正则表达式并返回布尔值,如果存在则返回 true,不存在则返回 false。
  • exec(string):用于在字符串中查找指定正则表达式,如果 exec()方法执行成功,则返回包含该查找字符串的相关信息数组。如果执行失败,则返回 null。
const reg1: RegExp = new RegExp('testreg');
console.log(reg1); // /testreg
const stra: string = 'testreg.com';
const res: boolean = reg1.test(stra);
console.log(res);
1
2
3
4
5
const stra: string = 'testreg.com';
const reg2: RegExp = new RegExp('testreg', 'gi');
const res2: any = reg1.exec(stra);
console.log(res2); // [ 'testreg', index: 0, input: 'testreg.com' ]
console.log(reg2); // /testreg/gi
1
2
3
4
5

enum(枚举)

定义格式如下:

enum 枚举名{
    标识符[=整型常数],
    标识符[=整型常数],
    ...
    标识符[=整型常数]
}
1
2
3
4
5
6

特别说明:如果标识符没有赋值,其值就是对应标识符的下标。如果赋值了,就是对应的初始值。

// 枚举类型
enum Roles {
    SUPER_ADMIN = 1, // 赋值初始值
    ADMIN = 4,
    USER
}
// 获取到的是索引值
console.log(Roles.SUPER_ADMIN); // 1
// 也可以根据索引值获取到对应的枚举属性值
console.log(Roles[4]); // 'ADMIN'

// 标识符的值是递增的
console.log(Roles.USER); // 5
1
2
3
4
5
6
7
8
9
10
11
12
13
enum SEX {man, woman, yao};
console.log(SEX.woman); // 这里返回1,是索引index值,跟数组很像
1
2
// 可以使用=给枚举赋值
enum SEX {
    man = '男人',
    woman = '女人',
    yao = '妖'
};
console.log(SEX.woman); // 女人
1
2
3
4
5
6
7
enum Flag {
    succuss = 1,
    error = 2,
    undedined = -1,
    null = -2
}
// 指定s和e均为枚举类型
let s:Flag = Flag.succuss;
let e:Flag = Flag.error;
let u:Flag = Flag.undedined;
let n:Flag = Flag.null;
console.log(s, e, u, n); // 1 2 -1 -2
1
2
3
4
5
6
7
8
9
10
11
12
// 枚举
// 默认情况从0开始为元素编号,也可手动为1开始
enum Color {Red=1, Green, Blue}
let c:Color = Color.Blue;
console.log(c); // 3
let colorName:string = Color[2];
console.log(colorName); // Green 因为上面代码里它的值是2
1
2
3
4
5
6
7

dadaf04970e14eade782e7f4aea132f5.png

any

基本用法

// 相当于es5中的没有类型校验
let anytest: any = 123;
anytest = 'test';

console.log(anytest);
1
2
3
4
5

any 类型的使用场景

const box: any = document.querySelector('.box');
box.style.color = 'red';
1
2

在 ts 中不设置 any 会报错:

2e33ccaee67efe429a6a2f78368810ff.png

null 和 undefined

null 和 undefined 是其他(never 类型)数据类型的子类型。

undefined

// 设置a是undefined类型
let a: undefined;
console.log(a); // 正确
1
2
3
// 设置a是null类型
let a: null;
a = 123; // 报错,只能赋值为null
1
2
3
let a: number;
console.log(a); // 报错
1
2
// num2为null、undefined或者数值类型
// 给一个元素设置多个类型
var num2: number | undefined | null;
num2 = 123;
console.log(num);
1
2
3
4
5

void

void 类型表示没有任何类型,一般用于定义没有返回值的方法。

// 表示run方法没有返回值
function run(): void {
  console.log(111);
}
// 指定为undefined表示该方法返回undefined
function run(): undefined {
  console.log(111);
  // 定义返回值为undefined,必须显式返回undefined
  return undefined;
}
1
2
3
4
5
6
7
8
9
10
// void类型
const fn = (str: string): void => {
  console.log(str);
  // 默认返回undefined
};
fn('test');
let kong: void;
kong = undefined;
// kong = null; // 报错,不能将null赋值给void类型
1
2
3
4
5
6
7
8
9

never

never 类型:即其他类型(包括 null 和 unfined)的子类型,代表从不会出现的值。never 类型的变量只能被 never 类型赋值。

let a: undefined;
a = undefined;

let b: null;
b = null;

let c: never;
c = (() => {
  throw new Error('错误');
})();
1
2
3
4
5
6
7
8
9
10
const errorFunc = (msg: string): never => {
  // 定义返回值是never类型
  throw new Error(msg);
};
const infiniteFunc = (): never => {
  // 死循环
  while (true) {}
};
1
2
3
4
5
6
7
8

上述两种情况:抛出错误和死循环都不会有返回值,因此可以指定返回值是 never 类型。

Object 类型

const func = (obj: object): string => {
  return `${obj}`;
};
func({ name: 'lisi' });
1
2
3
4

类型推论(类型断言)

如果没有明确的指定类型,那么 TypeScript 会依照类型推论(Type Inference)的规则推断出一个类型。

如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成 any 类型而完全不被类型检查。

const getLength = (target:string | number):number => {
    if ((<string>target).length || (target as string).length === 0) {
        return (target as string).length;
    } else {
        return target.toString().length;
    }
}
1
2
3
4
5
6
7

类型断言的两种写法:断言 target 为 string 类型。

  • (<string>target)
  • (target as string)

联合类型

联合类型(Union Types)表示取值可以为多种类型中的一种。

let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
1
2
3
let myFavoriteNumber: string | number;
myFavoriteNumber = true;

// index.ts(2,1): error TS2322: Type 'boolean' is not assignable to type 'string | number'.
//   Type 'boolean' is not assignable to type 'number'.
1
2
3
4
5

联合类型使用 | 分隔每个类型。这里的let myFavoriteNumber: string | number的含义是,允许 myFavoriteNumber 的类型是 string 或者 number,但是不能是其他类型。

访问联合类型的属性或方法

当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法:

function getLength(something: string | number): number {
  return something.length;
}

// index.ts(2,22): error TS2339: Property 'length' does not exist on type 'string | number'.
//   Property 'length' does not exist on type 'number'.
1
2
3
4
5
6

上例中,length 不是 string 和 number 的共有属性,所以会报错。 访问 string 和 number 的共有属性是没问题的:

function getString(something: string | number): string {
  return something.toString();
}
1
2
3

联合类型的变量在被赋值的时候,会根据类型推论的规则推断出一个类型:

let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
console.log(myFavoriteNumber.length); // 5
myFavoriteNumber = 7;
console.log(myFavoriteNumber.length); // 编译时报错

// index.ts(5,30): error TS2339: Property 'length' does not exist on type 'number'.
1
2
3
4
5
6
7

上例中,第二行的 myFavoriteNumber 被推断成了 string,访问它的 length 属性不会报错。 而第四行的 myFavoriteNumber 被推断成了 number,访问它的 length 属性时就报错了。