【TS】快速上手(二)类型声明

1,695 阅读7分钟

嗨!~ 大家好,我是YK菌 🐷 ,一个微系前端 ✨,爱思考,爱总结,爱记录,爱分享 🏹,欢迎关注我呀 😘 ~ [微信号: yk2012yk2012,微信公众号:ykyk2012]

「这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战

今天来介绍typescript的类型系统,主要是学习一些语法

参考链接:

1. 起步

  • 类型声明是TS非常重要的一个特点
  • 通过类型声明可以指定TS中变量(参数、形参)的类型
  • 指定类型后,当为变量赋值时,TS编译器会自动检查值是否符合类型声明,符合则赋值,否则报错
  • 简而言之,类型声明给变量设置了类型,使得变量只能存储某种类型的值

我们先来看看,TypeScript给变量指定类型的语法(类型注解)是什么

// 声明一个变量
let 变量: 类型

// 声明一个变量并给其赋值
let 变量: 类型 = 值

// 声明一个函数
function yk(参数: 参数类型): 函数返回值类型{ 
    //... 
}

这里我们可以看到,就是在变量后面就一个冒号,然后标识其类型就可以了

2. 类型

下面我们就来介绍介绍,TypeScript中到底有哪些类型

学过js你认识的类型:booleannumberstringundefinednullsymbolbigintobject

你可能不认识的类型:voidanyunknownnever

我们后面会详细的介绍这些你可能不认识的类型

2.1 变量

如果我们在声明变量指定类型后,之后如果给变量赋值为其他类型的值,编辑器会报错,如图所示

let n: number = 1
n = 3
n = '1' // 编辑器报错,不能将字符串赋值给number类型的变量

image.png

2.2 自动类型判断

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

image.png

那都可以省略了,还要自己写类型干嘛呢? 事实上,显式的写类型更有优势的地方是在函数定义的时候

2.3 函数

我们先回顾下用js声明一个函数的特点:js中的函数是不考虑参数的类型个数

function sum(a, b){
    return a + b
}

console.log(sum(1, 2)) // 3

console.log(sum(1, '2')) // '12'

而用ts定义

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

console.log(sum(1, 2)) // 3

image.png

参数数量也有限制

image.png

因为TS有类型推断,所以函数的返回值可以不用显式指定

function sum(x: number, y: number) => x + y

2.4 类型详解

基本类型我们就不详细谈了,我们来说说TS中一些特殊的类型

void

相信熟悉Java或者C的同学应该对void也不会陌生,当函数没有返回值的时候,定义函数的返回值类型就是void

其实我们知道,在JavaScript中,如果定义一个函数不写返回值,那么它默认是返回 undefined 的~

什么都不返回

function fn(): void {
}

只写一个return

function fn(): void {
  return 
}

返回一个undefined

function fn(): void {
  return undefined
}

我们返回一个null也是可以的

function fn(): void {
  return null
}

除了以上的几种情况,其他情况都是不行的

image.png

image.png

也就是说只有nullundefined可以赋给void

其实在JS中void是一种操作符,可以让任何表达式返回undefined

void 0 // undefined

为什么要这样呢,因为undefined在JS中不是一个保留字,可以通过声明变量来覆盖它

any

any 表示的是任意类型,一个变量设置类型为 any 后,相当于对该变量关闭了TS的类型检测。

隐式any:如果只声明变量不指定类型不给变量赋值,变量就是any类型的

当把any类型的变量可以赋值给其他类型的变量,不会报错

let a
let b: any
a = 1
a = '1'
b = '1'
b = 1

let c:string = '123'
c = b 

any类型是多人协作项目的大忌,很可能把Typescript变成AnyScript,通常在不得已的情况下,不应该首先考虑使用此类型。

unknown

开发的时候有些变量就是事先不知道的类型怎么办呢?可以使用unknown

unknownany的区别就是,将unknown类型变量赋值给其他任意类型的变量时,会报错

image.png

可以这样理解:unknown类型的变量就是类型安全的any,不能直接赋值给其他类型的变量

需要在赋值之前做好类型判断 (这叫缩小类型范围)

if (typeof b === 'string') {
  c = b
}

或者这样写 【类型断言】(相当于告诉解析器b就是一个string类型的变量)

c = b as string

c = <string>b

never

never 表示永远不会返回结果

  1. 报错
function error(): never{
    throw new Error('报错了!')
}
  1. 死循环
function endless(): never{
    while(true) {}
}

对象

image.png

一般来说,我们对于对象的类型检查一般是检查对象中有哪些属性,属性是什么类型。

可以用{} 来指定对象中可以包含哪些属性 语法:{属性名: 属性类型, ...}

image.png

属性多了少了都不行

image.png

可选属性,在属性名后面加一个 ?

let obj: {name: string, age?: number}
obj = {name: 'yk', age: 18}
obj = {name: 'yk'}

如果后续属性不确定叫什么名字,也不确定是什么类型,那么可以这样写[propName: string]: unknown

// 定义对象结构
let obj: { name: string, [propName: string]: unknown }

obj = {name: 'yk', age: 18, gender: 'male'}

函数

因为function是关键字,所有这里用Function来声明函数

let fn: Function

image.png

和对象一样,我们一般会限制函数有几个参数,参数的类型,返回值的类型,所以就可以以一种类似箭头函数的方式来声明一个函数类型的变量

// 定义函数结构
let fn: (a: number, b: number) => number

image.png

数组

比较常用的就是这种方式: 在元素类型后面接上 []:

let arr: number[] = [1, 2, 3]
let arr2: string[] = ['y', 'k']

还有一种是使用泛型(后面会说什么是泛型):

let list: Array<number> = [1, 2, 3]
let list2: Array<string> = ['y', 'k']
let list: Array<number | string> = [1, 2, 3, 'yk']

元组 Tuple

元组是TS新出的类型,表示固定长度的array

元组中包含的元素,必须与声明的类型一致,而且不能、不能,甚至顺序都不能不一样

image.png

image.png

字面量

也可以使用字面量去指定变量的类型,这相当于给他设置成了一个常量

let a: 10
a = 10

image.png

2.5 联合类型

可以给一个变量定义一个联合类型,类型名之间用 | 隔开

这个时候,字面量类型就有用了

let gender : "male" | "female"

此时gender只能被赋值成两个值

2.6 类型别名

这个时候,如果一个类型的字面量类型选择过多,重复编写就比较麻烦,这就可以使用类型别名

type myType = 1 | 2 | 3 | 4 | 5
let i: myType
let j: myType
let k: myType

k = 2

image.png

可以通过类型别名来定义函数参数类型结构

type fn = (x: number, y:number) => number // 这里fn表示类型

这个和之前定义函数结构是类似的

let fn: (x: number, y:number) => number // 这里fn表示值

但是使用类型别名使用起来就是这样

let fun: fn = (x, y) => x + y

2.7 总结

image.png

3. 类型断言

有些情况下,变量的类型对于我们来说是很明确,但是TS编译器却并不清楚,此时,可以通过类型断言来告诉编译器变量的类型,断言有两种形式:

第一种

let someValue: unknown = "this is a string";
let strLength: number = (someValue as string).length;

第二种

let someValue: unknown = "this is a string";
let strLength: number = (<string>someValue).length;

最后,欢迎关注我的专栏,和YK菌做好朋友