TS 类型基本用法
TS简介
- TypeScript,简称 TS, 是一种由微软开发的编程语言,它是对 JavaScript 的一个增强
- 让我们更加方便地进行类型检查和代码重构,提高代码的可靠性和可维护性
- 同时,TypeScript 还支持 ECMAScript 的最新特性
搭建学习环境
进入 Node 官网安装
安装完成后使用以下命令查看是否安装完成: 安装完成后使用以下命令查看是否安装完成:
node -v
npm -v
继续安装 nrm 管理包源:
npm i nrm -g
nrm ls
nrm use taobao
全局安装 typescript:
npm i typescript -g
全局安装 ts 的编译工具,使用 ts-node 可以将 ts 文件执行
npm i ts-node -g
- 使用:
ts-node index.ts
- 使用:
- 安装 ts-node 依赖包:
npm install tslib @types/node -g
使用 TS 可以有良好的提示,使代码可读性变强,更提前发现问题
TS 类型
- TS 出现弥补的 JS 的类型缺失
- 众所周知,代码错误越早发现越好,
代码编写 > 代码编译 > 代码运行
开发 > 测试 > 上线
- Vue2 使用
Flow
进行类型检查,后续 Vue3 也使用Typescript
重写 - TS 代码要运行在浏览器,需要进行类型擦除,转换为 JS 代码
- TS 类型包含所有 JS 类型 null、undefined、string、number、boolean、bigInt、Symbol、object(数组,对象,函数,日期)
- 还包含 void、never、enum、unknown、any 以及 自定义的 type 和 interface
变量声明
var/let/const 标识符: 数据类型 = 赋值
手动指定数据的类型(类型注解),不要写成大写的 String
,因为这是 JS 的一个内置类
const data: string = 'hello'
型定义的时候已经决定
类型推导
- 如果没有明确指定类型,TS 会隐式的推导出一个类型
- 这类型根据赋值的类型推断,没有赋值则为
any
类型,能自动推导出类型,没必要手动指定
基础类型
数组和元组
Array<元素类型>这种写法可能会存在与jsx冲突问题
const arr1: Array<number> = [1, 2, 3]
元素类型后面接上[],表示由此类型元素组成的一个数组
[const arr2: number[] = [1, 2, 3]
数组里面可能有字符串和数组
const arr3: (string | number)[] =
[1,2,'黛玉']
//元组已知元素数量和类型的数组,元组一定要指明类型
const tuple:[string, number] = ['云牧', 18]
- tuple可以作为函数返回的值,React 的 useState 就是个元组,类似于
function useState<T>(state: T): [T, (newState: T)=> void]
let currentState = state
const changeState = newState
currentState = newState
}
return [currentState, changeState]
[const [count, setCount]= useState(10)
对象类型
- TS 中的 object 类型泛指所有的的非原始类型,如对象、数组、函数
- 下面我们使用 object 声明了这个对象,但是这个对象既不能设置新数据,也不能修改老数据
const obj: object = {
name:'云牧',
}
obj.age = 18
obj.name='黛玉'
- 下面这种对象类型的限制才更为精确
- 可限制对象每个属性的类型
const p1:{name: string; age:number } = { name:'黛玉',age:18}
// 问号,代表某个属性可选,不一定需要
const p2: { name: string; age?: number } = {I name:'云牧'}
any、unknown、never
- 无法确定一个变量的类型,可使用
any
,此时在其身上做任何操作都是合法的,即使访问了一个不存在的属性 - 如果某些情况处理类型过于繁琐,或者在引入一些第三方库时,缺失了类型注解,这个时候 我们可以使用 any,更多是为了兼容老代码
function anyType(msg: any) {
console.log(msg)
}
unknown
类型表示一个值可以是任何类型,它是所有类型的父类型,任何类型都可以赋值给 unknown 类型,但是 unknown 类型只能赋值给 any 类型和 unknown 类型本身- 类似
any
,与any
类型不同的是,unknown
类型的变量不能直接赋值给其他类型的变量,也不能调用其上的任何方法或属性,除非先进行类型检查或类型断言,这样确保运行时的类型安全 - 默认在其操作都是不合法的,主要是在编写通用代码时,例如编写库或框架时,需要处理来自不同来源的数据,但又不确定数据的类型
//类型判断后才能使用 unknown类型数据
function foo(arg: unknown) {
if (typeof arg == 'string') {
console.log(arg.toUpperCase())
} else if (typeof arg == 'number') {
console.log(arg.toFixed(2))
}
}
//类型断言后使用
function bar(arg: unknown) {
const num = arg as number
console.log(num.toFixed(2))
}
- 假如一个函数的返回结果是死循环或者异常,我们可以使用
never
类型表示这种永不存在值的类型 - 它是一个底层类型,不是任何类型的子类型,也没有任何子类型
- 更多情况是封装工具库时候可以使用,比如下面这段代码,如果单纯在函数参数的类型多加一个参数,而没有对应
case
处理,则会报错
function handleMsg(msg: string | number) {
switch (typeof msg) {
case 'string
break
}
case 'number':
break
default: {
const check: never = msg
}
handleMsg('hello')
handleMsg(10)
never
会在联合类型被直接移除
函数类型
- 声明函数时,可以在每个参数后添加类型注解,声明其参数类型
- 同样也可以声明返回值的类型,不过也可以不写让 TS 自动推导
- 函数参数的一般顺序 必传参数 - 有默认值的参数 - 可选参数
枚举类型
- 枚举类型将一组可能出现的值,一个个列举,定义在一个类型中,这个类型就是枚举
这种字符串的枚举可能使用 type Direction = 'LEFT' | 'RIGHT' | 'TOP' | 'RIGHT'
可能会更好点
type Direction = 'LEFT'|'RIGHT'|'TOP'|'BOTTOM'
function turnDirection(direction: Direction) {}
turnDirection('LEFT')
interface 和 type
基本使用
- 使用 interface 定义接口,使用 type 定义类型别名
- 都可以约束对象的结构
// 方式一:使用interface
interface IPoint{
x: number
readonly y: number // readonly代表只读
z?:number //?代表可选
}
// 方式二:使用type
type Point = {
X: number
y: number
}
区别
- interface 只描述对象,type 则可以描述所有数据
- interface 使用 extends 来实现继承,type 使用 & 来实现交叉类型
- interface 会创建新的类型名,type 只是创建类型别名,并没有创建新类型
- interface 可以重复声明扩展,type 则不行(别名是不能重复的)
索引签名(Index Signatures)
接口继承
- 接口和类继承相同,都是使用
extends
关键字 - 接口是支持多继承的(类不支持多继承)
interface Animal {
running: () => void
}
interface Person{
name: string
age: number
}
//自动扩展 Person类型
interface Person {
sex: string
}
// 手动使用 extends 继承
interface Student extends Person, Animal {
id: number
}
const u: Student = { name:'云牧',age:18, sex: 'male', id: 1, running() }
接口实现
- 定义的接口可以被类实现
- 之后如果需要传入接口的地方,同样也可以将类实例传入
- 这就是面向接口开发
interface IRun {
running: () => void
}
interface IEating {
eating:() => void
}
class Person implements IRun, IEating {
running(){}
eating(){}
}
function run(runner: IRun) {
runner.running()
}
constp = new Person()
run(p)