TypeScript常用类型

概述

TypeScript是js的超集,ts提供了js的所有功能,并且额外的增加了: 类型系统

  • 所有的js代码都是ts代码
  • js有类型(number/string等),但是js不会检查变量的类型是否发生变化,而ts会检查

typescript类型系统的主要优势: 可以显示表基础代码中的意外行为,从而降低了发生错误的可能性

  1. 类型注解
  2. 常用基础类型

类型注解

示例代码:

let age: number = 18

说明: 代码中的 ' : number '就是类型注解

作用: 为变量添加类型约束,比如,上述代码中,约定变量 age 的类型为 number(数值类型)

解释: 约定了什么类型,就只能给变量赋值改类型的值,否则就会报错

TypeScript常用类型_第1张图片

常用基础类型概述

可以将ts中的常用基础类型细分为两类: 

  1. js已有类型
  2. ts新增类型

js已有类型

  • 原始类型: number/string/boolean/null/undefined/symbol
  • 对象类型: object(包括: 数组, 对象, 函数等)

ts新增类型

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

原始类型

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

特点: 简单,这些类型完全按照js中类型的名称来书写

let age: number = 18
let myName: string = 'zs'
let isLoading: boolean = false

数组类型(包括联合类型)

对象类型: object(包括,数组, 对象, 函数等)

特点: 对象类型,再ts中更加细化,每个具体的对象都有自己的类型语法

  • 数组类型的两种写法: (推荐使用 number[] 写法)
let number: number[] = [1, 3, 5]
let string: Array = ['a', 'b', 'c']

需求: 数组中既有number类型,又有string类型,可以用如下的方式

let arr: (number | string)[] = [1, 'a', 3, 'b']

解释: ' | '在ts中叫做联合类型(由两个或对各其他类型组成的类型,表示可以是这些类型中的任意一种)

注意: 这是ts中的联合类型的语法,只有一根竖线,需要与js中的或( || )进行区分

类型别名

类型别名(自定义类型): 为任意类型起别名

使用场景: 当同一类型(复杂)被多次使用是,可以通过类型别名,简化该类型的使用

type CustomArray = (number | string)[]
let arr1: CustomArray = [1, 'a', 3, 'b']
let arr2: CustomArray = ['x', 'y', 6, 7]

解释:

  1. 使用type关键字来创建类型别名
  2. 类型别名(比如上述 CustomArray),可以是人以合法的变量名称
  3. 创建类型别名后,直接使用该类型别名作为变量的类型注解即可

函数类型

函数的类型实际上指的是: 函数参数和返回值的类型

为函数指定类型的两种方式: 

1.单独指定参数,返回值的类型

function add(num1: number, num2: number): number {
    return num1 + num2
}
const add = (num1: number, num2: number): number => {
    return num1 + num2
}

2.同时指定参数,返回值的类型

const add: (num1: number num2: number) => number = (num1, num2) => {
    return num1 + num2
}

解释: 当函数作为表达式时,可以通过类似箭头函数形式的语法来为函数添加类型

注意: 这种形式只适用于函数表达式

3.void类型

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

function great(name: string): void {
    console.log('Hello', name)
}

void是一个特殊的函数返回值类型

可选参数

使用函数实现某个功能时,参数可以传也可以不传,这种情况下,在给函数参数指定类型时,就用到可选参数了

比如,数组的slice()方法,可以slice()也可以slice(1),还可以slice(1, 3)

function mySlice(start?: number, end?: number): void {
    console.log('起始索引: ', start, '结束索引: ', end)
}

在进行打印的时候,未填的可选参数展示undefined

可选参数: 可传可不穿的参数名称跟后面添加 ' ? '(问号)

注意: 可选参数只能出现在参数列表的最后,也就是说可选参数后面不能再出现必选参数

对象类型

js中的对象是由属性和方法构成的,而ts中对象的类型就是在描述对象的结构(有什么类型的属性和方法)

对象类型的写法:

let person: { name: string; age: number; sayHi(): void; greet(name: string): void } = {
  name: 'zs',
  age: 18,
  sayHi() {},
  greet(name) {}
}

解释:

  1. 直接使用 {} 来描述对象结构,属性采用属性名: 类型的形式;方法采用方法名(): 返回值类型的形式

  2. 如果方法有参数,九在方法名后面的小括号中指定参数类型(比如: greet(name: string): void)

  3. 在一行代码中指定对象的多个属性类型时,使用 ' ; ' (分号)来分隔

  • 如果一行代码中至指定一个属性类型(通过换行来分隔多个属性类型),可以去掉 ' ; '(分号),如下
  • 方法的类型也可以使用箭头函数形式(比如: { sayHi: () => void })
let person: {
  name: string
  age: number
  // sayHi(): void
  sayHi: () => void
  greet(name: string): void
  } = {
  name: 'zs',
  age: 18,
  sayHi() {},
  greet(name) {}
}

可选属性

对象的属性或方法,也是可选的

比如,在使用axios({...})时,如果发送GET请求,method属性就可以省略

function myAxios(config: { url: string; method?: string }) {
    console.log(config)
}

可选属性的语法与函数可选参数的语法一致,都使用 ' ? '(问号)来表示

接口

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

// let person: { name: string; age: number; sayHi(): void } = {
//   name: 'zs',
//   age: 18,
//   sayHi() {}
// }

// let person1: { name: string; age: number; sayHi(): void }

interface IPerson {
  name: string
  age: number
  sayHi(): void
}

let person2: IPerson = {
  name: 'zs',
  age: 18,
  sayHi() {}
}

解释:

  1. 使用 interface 关键字来声明接口
  2. 接口名称(比如,IPerson),可以是任意合法的变量名称
  3. 声明接口后,直接使用接口名称作为变量的类型
  4. 因为每一行只有一个属性类型,因此,属性类型后没有 ' ; '(分号)

接口和类型别名(对比)

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

  • 相同点: 都可以给对象指定类型
  • 不同点:
    • 接口,只能为对象指定类型
    • 类型别名,不仅可以为对象指定类型,实际上可以为任何类型指定别名
// 接口
interface IPerson {
    name: string,
    age: number,
    sayHi(): void
}
// 类型别名
type IPerson = {
    name: string
    age: number
    sayHi(): void
}
// 类型别名
type NumStr = number | string

接口的继承

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

比如,这两个接口都有x, y两个属性,重复写两次比较繁琐

interface Point2D { x:number; y: number }
interface Point3D { x:number; y: number; z: number }

更好的方式:

interface Point2D { x: number; y: number }
interface Point3D extends Point2D { z: number }

解释:

  1. 使用 extends (继承) 关键字实现了接口 Point3D 继承 Point2D
  2. 继承后, Point3D 就有了 Point2D 的所有属性和方法 (此时,Point3D 同时有 x, y, z 这三个属性)
interface Point2D { x: number; y: number }

// 使用 继承 实现复用
interface Point3D extends Point2D { z: number }

let p3: Point3D = {
  x: 1,
  y: 0,
  z: 2
}

元组

场景: 在地图中,使用经纬度坐标来标记位置信息

可以使用数组来记录坐标,那么,该数组中只有两个元素,并且这两个元素都是数值类型

let position: number[] = [39.5427, 116.2317]

使用 number[] 的缺点: 不严谨,因为改类型的数组中可以出现任意多个数字

更好的方式: 元组(Tuple)

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

let position: [number, number] = [39.5427, 116.2317]

解释:

  1. 元组类型可以确切的标记处有多少个元素,以及每个元素的类型
  2. 示例中,元素有两个元素,每个元素的类型都是number

类型注解

在TS中,某些没有明确指出类型的地方,TS的类型推论机制会帮助提供类型

发生类型推论的2中常见场景:

  1. 声明变量并初始化时
  2. 决定函数返回值时
// 注意: 如果声明变量但是没有立即初始化值 即赋值 必须手动添加类型注解
let age = 18

function add(num1: number, num2: number) {
  return num1 + num2
}

TypeScript常用类型_第2张图片

注意: 这两种情况下,类型注解可以省略不写

推荐: 能省略类型注解的地方就省略,提升开发效率,建议参数添加上类型注解

技巧: 如果不知道类型,可以通过鼠标放在变量名上,通过编译器提示查看类型

类型断言

有时候开发者比ts更明确一个值的类型,此时可以使用类型断言来指定更具体的类型

比如

传智教育

TypeScript常用类型_第3张图片

注意: getElementById 方法返回值的类型时 HTMLElement,改类型只包含所有标签公共的属性或方法,不包含 a 标签特有的 href 等属性

因此,这个类型太宽泛(不具体),无法操作 href 等 a 标签特有的属性或方法

解决方法: 这种情况下就需要使用类型断言指定更加具体的类型

使用类型断言:

const aLink = document.getElementById('link') as HTMLAnchorElement

TypeScript常用类型_第4张图片

TypeScript常用类型_第5张图片

解释:

  1. 使用 as 关键字实现类型断言
  2. 关键字 as 后面的类型是一个更加具体的类型( HTMLAnchorElement 是 HTMLElement 的子类型 )
  3. 通过类型断言,aLink的类型变得更加具体,这样就可以访问 a 标签特有的属性或方法了

另一种语法,使用 <> 语法,这种语法形式不常用:

const aLink = document.getElementById('link')

技巧: 在浏览器控制台,通过 console.dir() 打印 DOM 元素,在属性列表的最后面,即可看到该元素的类型

TypeScript常用类型_第6张图片

在浏览器中选中一个元素,标签后面显示 $0

去到控制台,输入

console.dir($0)

TypeScript常用类型_第7张图片

展开后在最底部即可看到元素类型

字面量类型

let str1 = 'Hello TS'
const str2 = 'Hello TS'

通过TS类型推论机制,就可以得到答案:

  1. 变量 str1 的类型为: string
  2. 变量 str2 的类型为: 'Hello TS'

你可能感兴趣的:(ts,javascript,typescript,前端)