小满 zs-Typescript

TS 是 JS 的超集,所以 JS 基础的类型都包含在内

起步安装

1
npm install typescript -g

基础类型:Boolean、Number、String、null、undefined 以及 ES6 的 Symbol 和 ES10 的 BigInt。

1.字符串类型

字符串是使用 string 定义的

1
2
3
4

let a: string = '123'
//普通声明
let str: string = `dddd${a}`

一键获取完整项目代码
TypeScript
其中 ` 用来定义 ES6 中的模板字符串,${expr} 用来在模板字符串中嵌入表达式。

2.数字类型

支持十六进制、十进制、八进制和二进制;

1
2
3
4
5
6
7
let notANumber: number = NaN;//Nan
let num: number = 123;//普通数字
let infinityNumber: number = Infinity;//无穷大
let decimal: number = 6;//十进制
let hex: number = 0xf00d;//十六进制
let binary: number = 0b1010;//二进制
let octal: number = 0o744;//八进制 s

3.布尔类型

注意,使用构造函数 Boolean 创造的对象不是布尔值:

1
2
3
4
5
6
7
8
9
10
let createdBoolean: boolean = new Boolean(1)
//这样会报错 应为事实上 new Boolean() 返回的是一个 Boolean 对象

事实上 new Boolean() 返回的是一个 Boolean 对象 需要改成

let createdBoolean: Boolean = new Boolean(1)
let booleand: boolean = true //可以直接使用布尔值

let booleand2: boolean = Boolean(1) //也可以通过函数返回布尔值

4.空值类型

JavaScript 没有空值(Void)的概念,在 TypeScript 中,可以用 void 表示没有任何返回值的函数

1
2
3
function voidFn(): void {
console.log('test void')
}

void 类型的用法,主要是用在我们不希望调用者关心函数返回值的情况下,比如通常的异步回调函数

void 也可以定义 undefined 和 null 类型

1
2
let u: void = undefined
let n: void = null;

5.Null 和 undefined 类型

1
2
let u: undefined = undefined;//定义 undefined
let n: null = null;//定义 null

void 和 undefined 和 null 最大的区别
与 void 的区别是,undefined 和 null 是所有类型的子类型。也就是说 undefined 类型的变量,可以赋值给 string 类型的变量:
这样写会报错 void 类型不可以分给其他类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let test: void = undefined
let num2: string = "1"
num2 = test
//这样是没问题的
let test: null = null
let num2: string = "1"

num2 = test

//或者这样的
let test: undefined = undefined
let num2: string = "1"

num2 = test

_Tips 注意:如果你配置了 tscofig.json 开启了严格模式, null 不能 赋予 void 类型 _

1
2
3
4
5
{
"compilerOptions":{
"strict": true
}
}

Any 类型 和 unknown 顶级类型

nodejs 环境执行 ts

1
2
npm i @types/node --save-dev (node环境支持的依赖必装)
npm i ts-node --g

1.没有强制限定哪种类型,随时切换类型都可以 我们可以对 any 进行任何操作,不需要检查类型

1
2
3
let anys:any = 123
anys = '123'
anys = true

2.声明变量的时候没有指定任意类型默认为 any

1
2
3
let anys;
anys = '123'
anys = true

3.弊端如果使用 any 就失去了 TS 类型检测的作用

4.TypeScript 3.0 中引入的 unknown 类型也被认为是 top type ,但它更安全。与 any 一样,所有类型都可以分配给 unknown

unknow unknow 类型比 any 更加严格当你要使用 any 的时候可以尝试使用 unknow

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

//unknown 可以定义任何类型的值
let value: unknown;

value = true; // OK
value = 42; // OK
value = "Hello World"; // OK
value = []; // OK
value = {}; // OK
value = null; // OK
value = undefined; // OK
value = Symbol("type"); // OK

//这样写会报错unknow类型不能作为子类型只能作为父类型 any可以作为父类型和子类型
//unknown类型不能赋值给其他类型
let names:unknown = '123'
let names2:string = names

//这样就没问题 any类型是可以的
let names:any = '123'
let names2:string = names

//unknown可赋值对象只有unknown 和 any
let bbb:unknown = '123'
let aaa:any= '456'

aaa = bbb

区别 2

如果是 any 类型在对象没有这个属性的时候还在获取是不会报错的

1
2
3

let obj:any = {b:1}
obj.a

如果是 unknow 是不能调用属性和方法

1
2
let obj:unknown = {b:1,ccc:():number=>213}
obj.b

对象的类型

在 typescript 中,我们定义对象的方式要用关键字 interface(接口),我的理解是使用 interface 来定义一种约束,让数据的结构满足约束的格式。定义方式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//这样写是会报错的 因为我们在 person 定义了 a,b 但是对象里面缺少 b 属性
//使用接口约束的时候不能多一个属性也不能少一个属性
//必须与接口保持一致
interface Person {
b:string,
a:string
}


const person:Person = {
a:"213"
}

//重名 interface 可以合并
interface A{name:string}
interface A{age:number}
var x:A={name:'xx',age:20}
//继承
interface A{
name:string
}

interface B extends A{
age:number
}

let obj:B = {
age:18,
name:"string"
}

可选属性 使用?操作符
//可选属性的含义是该属性可以不存在
//所以说这样写也是没问题的
interface Person {
b?:string,
a:string
}

const person:Person = {
a:"213"
}

任意属性 [propName: string]

需要注意的是,一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集:

1
2
3
4
5
6
7
8
//在这个例子当中我们看到接口中并没有定义 C 但是并没有报错
//应为我们定义了[propName: string]: any;
//允许添加新的任意属性
interface Person {
b?:string,
a:string,
[propName: string]: any;
}

只读属性 readonly

readonly 只读属性是不允许被赋值的只能读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//这样写是会报错的
//应为 a 是只读的不允许重新赋值
interface Person {
b?: string,
readonly a: string,
[propName: string]: any;
}

const person: Person = {
a: "213",
c: "123"
}

person.a = 123


interface Person {
b?: string,
readonly a: string,
[propName: string]: any;
cb:()=>void
}

const person: Person = {
a: "213",
c: "123",
cb:()=>{
console.log(123)
}
}

数组的类型

1.类型[ ]

1
2
3
4
5
6
7
8
9
10
11
//类型加中括号
let arr:number[] = [123]
//这样会报错定义了数字类型出现字符串是不允许的
let arr:number[] = [1,2,3,'1']
//操作方法添加也是不允许的
let arr:number[] = [1,2,3,]
arr.unshift('1')

var arr: number[] = [1, 2, 3]; //数字类型的数组
var arr2: string[] = ["1", "2"]; //字符串类型的数组
var arr3: any[] = [1, "2", true]; //任意类型的数组

数组泛型
规则 Array<类型>

1
let arr:Array<number> = [1,2,3,4,5]

用接口表示数组
一般用来描述类数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
interface NumberArray {
[index: number]: number;
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];
//表示:只要索引的类型是数字时,那么值的类型必须是数字。
多维数组
let data:number[][] = [[1,2], [3,4]];
arguments 类数组
function Arr(...args:any): void {
console.log(arguments)
//错误的 arguments 是类数组不能这样定义
let arr:number[] = arguments
}
Arr(111, 222, 333)

function Arr(...args:any): void {
console.log(arguments)
//ts 内置对象 IArguments 定义
let arr:IArguments = arguments
}
Arr(111, 222, 333)

//其中 IArguments 是 TypeScript 中定义好了的类型,它实际上就是:
interface IArguments {
[index: number]: any;
length: number;
callee: Function;
}

any 在数组中的应用
一个常见的例子数组中可以存在任意类型

1
let list: any[] = ['test', 1, [],{a:1}]

函数的类型

1
2
3
4
5
6
//注意,参数不能多传,也不能少传 必须按照约定的类型来
const fn = (name: string, age:number): string => {
return name + age
}
fn('张三',18)

函数的可选参数?

1
2
3
4
5
6
//通过?表示该参数为可选参数
const fn = (name: string, age?:number): string => {
return name + age
}
fn('张三')

函数参数的默认值

1
2
3
4
const fn = (name: string = "我是默认值"): string => {
return name
}
fn()

接口定义函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//定义参数 num 和 num2  :后面定义返回值的类型
interface Add {
(num: number, num2: number): number
}

const fn: Add = (num: number, num2: number): number => {
return num + num2
}
fn(5, 5)


interface User{
name: string;
age: number;
}
function getUserInfo(user: User): User {
return user
}

定义剩余参数

1
2
3
4
5
6
7
8
9
const fn = (array:number[],...items:any[]):any[] => {
console.log(array,items)
return items
}

let a:number[] = [1,2,3]

fn(a,'4','5','6')

函数重载

重载是方法名字相同,而参数不同,返回类型可以相同也可以不同。

如果参数类型不同,则参数类型应设置为 any。

参数数量不同你可以将不同的参数设置为可选。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function fn(params: number): void

function fn(params: string, params2: number): void

function fn(params: any, params2?: any): void {

console.log(params)

console.log(params2)

}



fn(123)

联合类型

1
2
3
4
5
6
7
//例如我们的手机号通常是13XXXXXXX 为数字类型 这时候产品说需要支持座机
//所以我们就可以使用联合类型支持座机字符串
let myPhone: number | string = '010-820'


//这样写是会报错的应为我们的联合类型只有数字和字符串并没有布尔值
let myPhone: number | string = true

函数使用联合类型

1
2
3
const fn = (something:number | boolean):boolean => {
return !!something
}

交叉类型

多种类型的集合,联合对象将具有所联合类型的所有成员

1
2
3
4
5
6
7
8
9
10
11
12
13
interface People {
age: number,
height: number
}
interface Man{
sex: string
}
const xiaoman = (man: People & Man) => {
console.log(man.age)
console.log(man.height)
console.log(man.sex)
}
xiaoman({age: 18,height: 180,sex: 'male'});

类型断言

语法:  值 as 类型  或  <类型>值 value as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
string  <string>value
interface A {
run: string
}

interface B {
build: string
}

const fn = (type: A | B): string => {
return type.run
}
//这样写是有警告的应为B的接口上面是没有定义run这个属性的


interface A {
run: string
}

interface B {
build: string
}

const fn = (type: A | B): string => {
return (type as A).run
}
//可以使用类型断言来推断他传入的是A接口的值

需要注意的是,类型断言只能够「欺骗」TypeScript 编译器,无法避免运行时的错误,反而滥用类型断言可能会导致运行时错误

1
2
3
4
5
使用any临时断言
window.abc = 123
//这样写会报错因为window没有abc这个东西
(window as any).abc = 123
//可以使用any临时断言在 any 类型的变量上,访问任何属性都是允许的。

as const是对字面值的断言,与const直接定义常量是有区别的

如果是普通类型跟直接const 声明是一样的

1
2
3
4
const names = '小满'
names = 'aa' //无法修改
let names2 = '小满' as const
names2 = 'aa' //无法修改
1
2
3
4
5
6
// 数组
let a1 = [10, 20] as const;
const a2 = [10, 20];

a1.unshift(30); // 错误,此时已经断言字面量为[10, 20],数据无法做任何修改
a2.unshift(30); // 通过,没有修改指针

类型断言是不具影响力的
在下面的例子中,将 something 断言为 boolean 虽然可以通过编译,但是并没有什么用 并不会影响结果, 因为编译过程中会删除类型断言

1
2
3
4
5
6
function toBoolean(something: any): boolean {
return something as boolean;
}

toBoolean(1);
// 返回值为 1