目录

TypeScript常用类型

类型注解

TS类型概述

原始类型

数组类型

对象类型

函数类型

类型别名

接口

元组

字面量类型

枚举

any类型

typeof操作符

类型推论

类型断言

TypeScript常用类型

TypeScript是JS的超集,TS提供了JS的所有功能,并额外增加了类型系统

JS有类型,但是JS不会检查变量的类型是否发生变化,而TS会检查。TypeScript类型系统的主要优势:可以显示标记出代码的意外行为,从而降低了发生错误的可能性。

类型注解

类型注解就是为了给代码添加类型约束,如下代码中 : number

let age: number = 12

上述代码中,约定变量age的类型为number(数值类型),即约定了什么类型就只能给变量赋值该类型的值,否则就会报错。如下所示:

typescript 局部注册组件 typescript 类型注解_typescript 局部注册组件

TS类型概述

在TS中常用的基础类型细分为两类:一类是JS已有类型,另一类是TS新增类型。

JS已有类型

1)原始类型:number/string/boolean/null/undefined/symbol。

2)对象类型:object(包括:数组、对象、函数等)。

TS新增类型

联合类型、自定义类型(类型别名)、接口、元组、字面量类型、枚举、void、any等。

原始类型

原始类型:number/string/boolean/null/undefined/symbol。特点:简单,这些类型完全是按照JS中的类型名称来书写的。

原始类型中也就 symbol 是ES6引入了一种新的原始数据类型

let age: number = 12
let myname: string = '张三'
let isloding: boolean = true
let a: null = null
let b: undefined = undefined
let s: symbol = Symbol()

数组类型

数组类型的两种写法:(推荐使用number[]写法)

let numbers: number[] = [1,2,3,4,5]
let string: Array<string> = ['1','2','3','4','5']

当我们要求数组中既有 number 类型,又有 string 类型,可以通过以下方式书写:

let arr: (number | string)[] = [1,'2',3,'4',5]

竖线 “|” 在TS中叫做联合类型(由两个或多个其他类型组成的类型,表示可以是这些类型中的任意一种)。

对象类型

JS中的对象是由属性和方法构成,而TS中对象的类型就是在描述对象的结构(有什么类型的属性和方法)。其写法如下:

let person: { name: string; age: number; say(): void; doing(Do: string): void} = {
  name:'张三',
  age: 18,
  say(){},
  doing(Do){}
}

如果一行代码只指定一个属性类型,可以换行来分隔多个属性类型,这样可以去掉分号 ;,如下

let person: { name: string
  age: number
  say(): void
  doing(Do: string): void
} = {
  name:'张三',
  age: 18,
  say(){},
  doing(Do){}
}

方法的类型也可以使用箭头函数形式,如下:

typescript 局部注册组件 typescript 类型注解_前端_02

对象的属性或方法也是可选的,此时就用到可选属性。可选属性的语法与函数可选参数的语法一致,都是用 ?(问号) 来表示,案例如下:

function myaxios(config: {url: string, method?: string}){}

myaxios({
  url:''
})

函数类型

函数类型实际上指的是:函数参数返回值的类型。为函数指定类型有以下两种方式:

单独指定参数返回值类型:

function add1(n: number,m: number):number{
  return n+m
}
const add2 = (n: number,m: number): number =>{
  return n+m
}

同时指定参数返回值类型:

// 当函数作为表达式时,可以通过类似箭头函数形式的语法来为函数添加类型。
// 注意:这种形式只适用于函数表达式。
const add2: (n: number,m: number) => number = (n,m)=>{
  return n+m
}

void:如果函数没有返回值,那么函数返回值的类型为:void。如下:

function say(word: string): void{
  console.log('hello',word);
}
say('world')

typescript 局部注册组件 typescript 类型注解_javascript_03

可选参数:使用函数实现某个功能时,参数可以传也可以不传。这种情况下,在给函数参数指定类型时,就用到可选参数了。注意:可选参数只能出现在参数列表的最后,也就是说可选参数后面不能再出现必选参数。如下:

// 可选参数:在可传可不传的参数名称后面添加 ? (问号)
function myslice(start: number,end?: number): void{
  console.log('必选参数:',start,'可选参数:',end);
}
myslice(1)
myslice(1,2)

typescript 局部注册组件 typescript 类型注解_开发语言_04

类型别名

类型别名(自定义类型):为任意类型起别名。当同一类型(复杂)被多次使用时,可以通过类型别名,简化该类型的使用。如下:

// 使用 type 关键字来创建类型别名,类型别名可以是任意合法的变量名称
type unnumber = (number | string)[]
// 创建类型别名,直接使用该类型别名作为变量的类型注解即可。
let arr1: unnumber = [1,'2','s','3',12]
let arr2: unnumber = ['y',2,'v','3',2]

接口

当一个对象类型被多次使用时,一般会使用接口(interface)来描述对象的类型,达到复用的目的。

// 使用 interface 关键字声明接口
// 因为每一行只有一个属性类型,因此属性类型后面可以没有 分号 ;
interface myperson {
  name: string
  age: number
  say(): void
}
// 接口声明后,直接使用接口名称作为变量的类型
let person: myperson = {
  name:"张三",
  age:18,
  say(){}
}

let person1: myperson = {
  name:"李四",
  age:22,
  say(){}
}

接口继承:如果两个接口之间有相同的属性或方法,可以将公共的属性和方法抽离出来,通过继承来实现复用。案例如下:

interface Tom {
  name:string
  age: number
  sex:string
}
// 使用 extends (继承)关键字实现接口 Jack 继承 Tom,此时Jack就有了Tom所有属性和方法
interface Jack extends Tom { hobby: string}

type(类型别名)与 interface(接口)的对比

相同点:都可以给对象指定类型。

不同点:接口只能为对象指定类型;类型别名不仅可以为对象指定类型,实际上可以为任意类型指定别名。

typescript 局部注册组件 typescript 类型注解_javascript_05

元组

元组类型是另一种类型的数组,它确切的知道包含多少个元素,以及特定索引值所对应的类型。

// 元组中有两个元素且都为number类型,所以数组元素只能是两个number类型的元素
let position: [number,number] = [122.33,33.333]

字面量类型

字面量类型就是把某个具体的特定的类型作为TS的类型,如下:

typescript 局部注册组件 typescript 类型注解_前端_06

此处的 'hello' 就是一个字面量类型,除字符串外任何JS字面量(对象、数组等)都可作为类型使用。

字面量类型一般配合联合类型一起使用,比如在游戏中,游戏的方向只能是上下左右四种情况任意一个,用特定的字符串来表示上下左右比直接使用 string 类型更加精确严谨。如下:

function changeDirection(directive: 'up' | 'down' | 'left' | 'right'){}
changeDirection('left')

枚举

枚举功能类似于字面量类型+联合类型组合的功能,也可以表示一组明确的可选值。枚举:定义一组命名常量,它描述一个值,该值可以是这些命名常量中的一个。

// 使用 enum 关键字定义枚举
enum Direction {
  Up,Down,Left,Right
}

function changeDirection(direction: Direction){}

// 类似于JS中的对象,直接通过 .语法访问枚举成员。
changeDirection(Direction.Up)

注意:枚举成员是有值的,默认是从 0 开始自增的数值,当然我们也可以为枚举成员初始化值。

typescript 局部注册组件 typescript 类型注解_javascript_07

字符串枚举:枚举成员的值为字符串。

注意:字符串枚举没有自增长行为,因此字符串枚举的每个成员必须都有初始值。

typescript 局部注册组件 typescript 类型注解_typescript 局部注册组件_08

总结

枚举是TS为数不多的非JS类型扩展的特性之一,因为其他类型仅仅被当作类型,而枚举不仅用作类型,还提供值(枚举成员都是有值的)。也就是说其他类型会在编译JS代码时自动移除而枚举类型会被编译成JS代码!如下:

typescript 局部注册组件 typescript 类型注解_javascript_09

枚举与前面讲到的字面量+联合类型组合的功能类似,都是用来表示一组明确的可选值列表。

一般情况下推荐字面量类型+联合类型的方式,相对枚举来说,这种方式更加直观简洁。

any类型

当值为any类型时,可以对该值进行任意操作,并且不会有代码提示。这样就是失去了TS类型的保护优势,所以不推荐使用。除非临时使用 any 来避免书写很长很复杂的类型!

let a: any = 122
a = '212'//没有报错
a(12)//没有报错

以下具有any类型的隐式情况:

typescript 局部注册组件 typescript 类型注解_typescript 局部注册组件_10

typeof操作符

众所周知,JS中提供了typeof操作符,用来在JS中获取数据的类型。

console.log(typoef 'hello');//打印 string

TS也提供了typeof操作符,可以在类型上下文中引用变量或属性的类型(类型查询),根据已有变量的值,获取该值的类型,来简化类型的书写。

typescript 局部注册组件 typescript 类型注解_javascript_11

注意:typeof只能用来查询变量或属性的值,无法查询其他形式的类型,比如函数调用类型

typescript 局部注册组件 typescript 类型注解_typescript 局部注册组件_12

总结

number:任意数字、string:任意字符串、boolean:布尔值、字面量:其本身、any:任意类型、unknown:类型安全的any、void:undefined、never:不能是任何值、object:任意的JS对象、array:任意JS数组、tuple:TS新增类型,固定长度数组、enum:枚举

类型推论

在TS中,某些没有明确指出类型的地方,TS的类型推论机制会帮助提供类型。换句话说:由于类型推论的存在,某些地方的类型注解可以省略不写!而发生类型推论有两种常见场景:1、声明变量并初始化值 2、决定变量返回值时。推荐:能省略类型注解的地方就省略,如果不知道类型,可以通过鼠标放在变量名称上,利用VScode的提示来查看类型。

typescript 局部注册组件 typescript 类型注解_前端_13

类型断言

在日常开发中,有时你会比TS更加明确一个值的类型,此时可以使用类型断言来指定更具体的类型。比如我们要如何拿到a标签的href属性呢?

typescript 局部注册组件 typescript 类型注解_typescript_14

我们知道getElementById方法返回值的类型是HTMLElement,该类型只包含所有标签的公共属性或方法,不好含a标签特有的href属性,因此这个类型太宽泛,无法操作某些标签特有的属性或方法,这个时候就需要用到类型断言了。

使用类型断言,如下:

通过类型断言,a的类型变的更具体,这样就可以访问a标签特有的属性或方法了。

// 使用as关键字实现类型断言
// as关键字后面的类型是一个更具体的类型 HTMLAnchorElement 是 HTMLElement的子类型
const a = document.getElementById('a') as HTMLAnchorElement
a.href

 另一种语法,使用 <> 语法(这种语法不常用,了解即可),如下:

// 使用as关键字实现类型断言
// as关键字后面的类型是一个更具体的类型 HTMLAnchorElement 是 HTMLElement的子类型
const a = <HTMLAnchorElement>document.getElementById('a')
a.href