一、准备工作
1.1 安装 TS
npm install -g typescript
/yarn global add typescript
1.2 检测是否安装成功
- 能看到版本号就表示安装成功;
tsc -v
1.3 更新 TypeScript
的版本
npm update -g typescript**@latest
1.4 ❌ 运行 TS 文件(不推荐)
运行命令:
tsc 文件路径
(有些时候tsc不行,tsc.cmd 文件路径
);会生成对应的js文件, 运行js文件即可;
1.5 ✅ 简化 运行TS 步骤(推荐)
全局安装
ts-node
包:npm i -g ts-node
/yarn global add ts-node
使用方式:
ts-node 文件路径
解释:ts-node命令在内部偷偷的将TS转换为JS,然后,在运行JS代码,此命令并没有生成一个 JS 文件,只是在内部将TS转换为JS(如果之前有JS文件,修改TS文件并用此命令运行后,JS里的内容还是之前的,并没有同步);
注意:
- 在使用这种方式运行 ts 文件时,可能会报错:
error TS2584: Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.
- 原因:
console
不属于ECMAScript
标准。DOM里面的console
是浏览器环境下的(是window
对象里面的),属于浏览器BOM API
,Node
里面的console
是NodeJS
里面的,由NodeJS
自己定义的API,两者虽然由同样的功能,但是并不是同一个东西; - 解决方法:
- 安装
npm i -D tslib @types/node
;- 该命令是安装
TypScript
助手的运行库,包含所有TypeScript
辅助函数;
- 该命令是安装
- 安装到哪里根据自己定义,你也可以选择安装到全局(将
-D
改成-g
即可);
- 安装
1.6 TS 和 JS 的区别
TypeScript
是 JS 的超集,TS 提供了 JS 的 所有功能,并且额外的增加了:类型系统
;- 所有的JS代码都是TS代码;
- JS有类型(number、string、boolean、null、undefined、object、array......),但是
JS不会检查变量的类型是否发生变化
。而TS会检查
; TypeScript
类型系统的主要优势:可以显示标记出代码中的意外行为
,从而降低了发生错误的可能性;
二、 类型注解
-
概念 :
- 给 变量 添加 类型约束 ,使变量 只能被赋值为约定好的类型,同时可以有相关的类型提示;
-
作用 :
- 限制变量能赋值的数据类型并给出提示;
-
解释 :
- 约定了什么类型,就只能给变量赋该类型的值(赋别的类型的值会报错);
-
语法 :
ts变量: 类型
-
代码展示:
tsx// : number - 就是类型注解 // 约束变量的类型 - 约束的是什么类型,就只能给这个变量赋该类型的值,否则会报错 let age: number = 23 age = 24 // age = '24' - 报错:不能将类型"string",分配给类型"number"
-
说明:
: number
就是类型注解
,约束变量age
只能被赋值为number
类型,同时可以有number
类型相关的提示;
三、 常用基础类型
3.1 类型分类
- 可以将TS中的常用 基础类型 细分为 两类 :
- JS已有类型;
- TS新增类型
3.1.1 JS已有类型
-
基本数据类型 :
number
、string
、boolean
、null
、undefined
、symbol
;- 特点:简单,完全按照JS中类型的名称来书写;
-
symbol
:-
表示独一无二的值,最大的用法是用来定义对象的唯一属性名;
-
Symbol
函数栈不能用new
命令,因为Symbol
是原始数据类型,不是函数。可以接受一个字符串作为参数,为新创建的Symbol
提供描述,用来显示在控制台或者作为字符串的时候使用,便于区分;tsxconst a: number = 1; const b: string = '1'; const c: boolean = true; const d: undefined = undefined; const e: null = null; const f: symbol = Symbol('symbol');
-
-
引用数据类型 :
object
(数组、对象、函数、......);- 特点 :对象类型,在TS中更加细化,每个具体的对象都有自己的类型语法;
tsx// 数组类型的两种写法:(推荐第一种写法) // ✅ 数值类型数组 - 因为已经约束为number类型,所以在该数组中只能出现number类型,不能出现其他类型 const arr: number[] = [1, 2]; // ❌ 字符串类型数组 - 不推荐 const arr1: Array<number> = [1, 2]; const obj: { name: string age: number sayHi(): void // 参数可传可不传 greet: (type?: string) => void } = { name: '奥特曼', age: 12, sayHi: () => {}, greet: (type) => type }; obj.greet(); const timeObj: { startTime: number endTime: Date } = { startTime: new Date().getTime(), endTime: new Date() };
3.1.2 TS新增类型
- 联合类型(
|
); - 自定义类型(类型别名)(
type
); - 接口(
interface
); - 元组(
特殊的数组
); - 字面量类型;
- 枚举(
enum
); void
(空);- 泛型;
any
(任何类型)等;
3.1.3 ❗ 注意
-
简单类型 的 类型名 只能是 小写 ;
-
有时候发现,类型名首字母大写,也不会报错,但是所表达的意思就不一样了;
- 小写:表示该变量的值是
string
类型; - 大写:表示该变量是一个实例对象;
- 为什么大写的
String
也可以?- 像数字、字符串等,在
JS
内部有个 内部包装类 ,当我们把 字符串当对象使用的时候,在 js 内部会帮我们自动进行包装;
- 像数字、字符串等,在
ts// 类型名小写 // 约束变量的str的类型是 string 类型 let str: string = '13'; // 类型名大写 // 此处的意思是 str1 表示是个 实例对象,是 String 的 实例对象 let str1: String = '123'; // 这种才是 大写 String 的正确赋值方法 let str2: String = new String('123');
- 小写:表示该变量的值是
3.2 数组类型注解
-
数组 的 类型注解 有 两种方式:
- ✅ 方式一:
ts// 字符串类型的数组 const arr: string[] = ['1']; // 数字类型的数组 const arr1: number[] = [1]; // 对象类型的数组 const objArr: object[] = []
- ❌ 方式二(泛型写法):
ts// 数字类型的数组 const arr; Array<number> = [1]; // 字符串类型的数组 const str: Array<string> = ['1'];
3.3 联合类型
联合类型(
|
):由 两个 或 多个 其他类型 组成的 类型 ,表示可以是 这些类型 中的 任意一种;
-
代码展示:
tsx// 联合类型 - | // 添加小括号:首先是数组,其次,这个数组中元素的类型 let arr: (number | string | boolean | object)[] = [1, true, 'a', {name: '哈哈'}] // ❗ 注意区分 // 不添加小括号:test既可以是数字 也可以是 字符串型的数组 let test: number | string[] = 1 let test1: number | string[] = ['a']
-
🔺 注意 :
- 添加小括号 :
- 可以是 许多类型 中的 任意一种;
- 也可是 多种类型 同时出现;
- 不添加小括号 :
const a = string | number[] = 1;
const a = string | number[] = ['1', '2'];
- 既可以是
string
类型,也可以是number
类型的数组; - 多种类型 只能同时 出现一个;
- 添加小括号 :
3.4 类型别名(自定义类型)
3.4.1 基本使用
-
类型别名 :
- 自定义类型
- 为任意类型起别名;
-
使用场景 :
- 当同一类型(比较复杂的类型)被多次使用时,可以通过类型别名,简化该类型的使用;
解释:
- 使用
type
关键字类创建类型别名; - 类型别名可以是任意合法的变量名称;
- 创建类型别名后,直接 使用该类型别名作为变量的类型注解 即可;
-
语法 :
tstype 类型别名 = { 定义类型 };
-
❗ 注意 :
- 类型别名的命名采用规范的 大驼峰格式;
- 类型别名 不能 重复定义;
-
代码展示:
tsx
/**
* 使用 type 关键字来创建类型别名
* 类型别名可以是任意合法的变量名称
* 创建类型别名后,直接 使用该类型别名作为变量的类型注解 即可
*/
type CustomArray = (number | string)[]
let arr1: CustomArray = [1, 2, 'a']
let arr2: CustomArray = ['x', 'y', 'z', 6, 7]
3.4.2 type + 交叉类型模拟继承
-
类型别名 配合 交叉类型 (
&
)可以 模拟 继承,同样可以实现类型复用; -
代码展示:
ts// 父接口 type GoodsType = { id: string; price: number; } // 子接口继承 type DIsGoodsType = GoodsType & { disPrice: number; }
3.5 函数类型
-
函数类型 :
- 实际上指的是 函数 参数 和 返回值 的类型;
-
为函数指定类型的有两种方式:
-
单独指定参数、返回值的类型 :
ts// 单独指定参数和返回值类型 - 声明式函数 + 函数表达式 function add0(a: number, b: number): number { return a + b; } // 设置参数默认值 function add(a: number = 0, b: number = 0): number { return a + b; } const add1 = (a: number, b: number): number => a + b; // 设置参数默认值 const add2 = (a: number = 1, b: number = 1): number => a + b;
-
同时指定参数、返回值的类型 :(❗只适用于函数表达式 )
ts// 同时给 参数 和 返回值 指定类型 // 同时指定参数和返回值类型 - 只适用于 函数表达式 const sub: (a: number, b: number) => number = (a, b) => a - b; // 设置参数默认值 const sub1: (a: number, b: number) => number = (a = 0, b = 0) => a - b;
-
-
🔺注意 :
- 如果 函数 没有 返回值 ,那么,函数 返回值 类型为:
void
;
tsx// 如果函数没有返回值,那么,函数返回值的类型为void function add(name: string): void { console.log(name); } add('小Q');
- ❗ 可选参数 :
- 在 可传 可不传 的 参数名称 后面 添加
?
; - 注意 :
- 可选参数 只能出现 在 参数列表 的 最后,也就是说可选参数后面不能再出现必选参数;
- 在 可传 可不传 的 参数名称 后面 添加
- 如果 函数 没有 返回值 ,那么,函数 返回值 类型为:
3.6 对象类型
- JS 中的 对象 是由 属性 和 方法 构成 的;
- TS 中 对象 的 类型 就是在 描述对象 结构(由什么类型的属性和方法);
- ❗ 注意 :
- 直接使用
{}
来描述对象结构;- 属性 采用 属性名:类型 的形式;
- 方法 采用 方法名(): 返回值类型 的形式;
- 如果 方法 有 参数 ,就在 方法名 后面的 小括号 中 指定参数类型 (比如:
greet(name: string): void
); - 在 一行代码 中 指定对象的多个属性类型 时,使用
;
来分隔- 如果 一行代码 中 只指定一个属性类型 (通过换行来分隔多个属性类型),可以去掉
;
; - 方法的类型 也可以使用 箭头函数形式;
- 如果 一行代码 中 只指定一个属性类型 (通过换行来分隔多个属性类型),可以去掉
- 直接使用
- 对象类型的写法:
tsx
// ❌
let person: {name: string; age: number; sayHi(): void; greet?:(str: string) => void} = {
name: '邵秋华',
age: 23,
sayHi() {},
greet(str) {}
}
// 和上面的写法意义是一样的,更推荐下面这种,写起来方便很多
// ✅
let person: {
name: string
age: number
sayHi(): void
greet?:(str: string) => void
} = {
name: '邵秋华',
age: 23,
sayHi() {},
greet(str) {}
}
3.6.1 对象可选属性
-
可选属性的语法与函数可选参数的语法一致,都是用
?
来表示; -
代码展示:
tsxfunction myAxios(config: {url: string; method?: string}): void { console.log(config); } const myAxios1: (config: {url: string; method?: string}) => void = (config) => { console.log(config); } myAxios({ url: '哈哈嘻嘻', method: 'POST' }) myAxios1({ url: '嘻嘻哈哈' })
3.7 接口
-
当一个 对象类型 被 多次使用 的时候,一般会使用 接口(interface) 来描述 对象类型,达到复用的目的;
-
作用 :
- 在
TS
中使用interface
接口来描述对象的数据类型(常用于给对象的属性和方法添加类型约束);
- 在
-
解决了什么问题 :
- 类型的复用问题;
-
❗ 注意 :
-
使用
interface
关键字来声明接口; -
接口名称,可以是任意合法的变量名称;
-
声明接口后,直接使用 接口名称 作为变量的类型;
-
因为每一行只有一个属性类型,因此,属性类型后面没有
;
; -
一般很少使用
object
,基本都是使用interface
去定义对象,更加准确; -
interface
接口类型实际限制的是 字段名 和 字段的类型; -
interfacee
是可以重名的;- 第一个接口后面的接口就相当于给第一个接口增加类型;
tsinterface A { msg: string; status: number } interface A { code: number } // 现在的 A 就等于下面这样 interafce A { msg: string; status: number; code: number }
-
-
代码展示:
tsx// 定义接口 interface IPerson { name: string age: number work: string city: string sayHi(): void greet: (str: string) => void } // 使用接口 const obj: IPerson = { name: '邵秋华', age: 24, work: '中级Web前端开发工程师', city: '武汉', sayHi() {}, greet(str) {} } console.log(obj);
-
接口练习:
- 下面
interface
中的 分号 可以 省略;
ts// 后端返回到数据 /* { message: [ { image_src: "", open_type: "", goods_id: 122, navigator_url: "" } ], meta: { msg: "", status: 200 } } */ // 方式一 ✅:使用多个 interface interface BannerInfo { image_src: string; open_type: string; goods_id: number; navigator_url: string; } interface ResInfo { msg: string; status: number; } interface BannerRes { message: BannerInfo[]; meta: ResInfo } // 方式二 ❌:纯手写 interface BannerRes { message: Array<{ image_src: string; open_type: string; goods_id: number; navigator_url: string; }>; meta: { msg: string; status: number } } interface BannerRes { message: { image_src: string; open_type: string; goods_id: number; navigator_url: string; }[]; meta: { msg: string; status: number } }
- 下面
3.7.1 接口的继承
-
如果两个接口之间有相同的属性或方法,可以将公共的属性或方法抽出来,通过继承来实现复用;
-
接口的继承使用过关键字
extends
; -
代码展示:
tsxinterface Meta { msg: string; status: number; } // 接口 Res1 继承 Meta interface Res1 extends Meta { success: boolean } const xiHa: Res1 = { success: true, msg: "", status: 200 }
解释:
- 使用
extends
(继承) 关键字实现了接口 Res1 继承 Meta;- 继承后,Res1 就有了 Meta 的所有属性和方法;
3.7.2 接口的可选字段
-
概念 :
- 通过
?
对属性进行可选标注,赋值的时候 该属性可以缺失,如果有值必须保证类型满足要求;
- 通过
-
代码展示:
tsinterface Res { msg: string; status: number; code: number; success?: boolean } const resInfo: Res = { msg: "", status: 200, code: 200 }
3.7.3 接口和类型别名的对比
- 相同点 :
- 都可以 给 对象 指定类型;
- 都能实现继承的效果:
interface
使用extends
;type
配合 交叉类型 模拟 继承;
- 不同点 :
- 接口 :
- 只能 为 对象 指定类型;
- 同名的接口会合并(属性取并集,不能出现类型冲突);
- 类型别名 :
- 可以为 任意类型 指定 别名;
- 不能声明同名的
type
(会报错);
- 接口 :
3.8 元组
-
元组 :元组类型是另一种类型的数组,它 确切 地 知道 包含 多少 个 元素 ,以及 特定元素 对应 的 类型 ;
tsx// 只能写两个元素,并且都是 number类型的 let position: [number, number] = [256, 134]
3.9 类型推断
- 发生类型推断的2种常见场景:
- 声明变量并初始化;
- 决定函数返回值时;
- 这两种情况下,类型注解可以省略不写;
3.10 类型断言
-
作用 :
- 有些时候开发者比TS本身更清楚当前的类型是什么,可以使用断言(
as
)让类型更加精确和具体;
- 有些时候开发者比TS本身更清楚当前的类型是什么,可以使用断言(
-
使用
as
关键字实现 类型断言; -
关键字
as
后面的类型是一个 更加具体的类型 (HTMLAnchorElement
是HTMLElement
的子类型); -
通过类型断言,aLink的类型变得更加具体,这样就可以访问a标签特有的属性或方法了
tsxconst aLink = document.getElementById('link') as HTMLAnchorElement
-
❌ 另一种语法
<>
tsxconst aLink = <HTMLAnchorElement>document.getElemetById('link')
-
代码展示:
tsfunction fix(a: number | string, b: number | string): number | string | null { if (typeof(a) === "number" && typeof(b) === "number") return a + b; if (typeof(a) === "string" && typeof(b) === "string") return a + b; return null; }
- 不进行类型断言:
- 提示的是 string 和 number 共有的方法或属性;
- 将
res
断言为 number:- 提示的都是和 number 相关的方法或属性;
- 将
res
断言为 string:- 提示的都是和 string 相关的方法或属性;
- 将
res
断言为 null:- null没有属性和方法,所以什么都不提示
- 不进行类型断言:
-
拓展 :
- 查看类型
console.dir(xxx)
最后面就有类型([[Prototype]]: 类型
);
- 查看类型
3.11 字面量类型
- 字面量类型通常和联合类型(
|
)一起使用; - 字面量类型与常规类型相比的优势是什么?
- 类型更加精确;
- 提供精确的可选值范围;
ts
// 字面量类型
type Gender = 1 | 2;
// 只能给 gender 赋值为 1 | 2
const gender: Gender = 1;
tsx
// str 是用 let 声明的,是一个变量,它的值可以是任意字符串,所以类型为:string
let str = '123'
// hello 是用 const 声明的,是一个常量,它的值不能变化只能是'hello ts',所以类型为:'hello ts'
const hello = 'hello ts'
/**
* obj 也是用 const 声明的,它的值也不能变化,所以类型为:
* obj: {
* name: string
* age: number
* }
*/
const obj = {
name: '邵秋华',
age: 23
}
/**
* 同理,arr的类型为:
* arr: (number | string)[]
*/
const arr = [1, 2, '3']
/**
* 除字符串外,任意的JS字面量(对象、数字、数组......)都可以作为类型使用
*/
- 使用模式 :
- 字面量类型 配合 联合类型 一起使用;
- 使用场景 :
- 用来 表示一组明确的可选值列表;
- 优势 :
- 相比于 string 类型,使用字面量类型更加精确、严谨;
tsx
// 在贪吃蛇游戏中,游戏的方向的可选值只能是上、下、左、右中的任意一个
function changeDirection(direction: 'up' | 'down' | 'left' | 'right') {
console.log(direction)
}
changeDirection('left')
/**
* 解释:参数 direction 的值只能是 up/down/left/right 中的任意一个
* 优势:相比于 string 类型,使用字面量类型更加精确、严谨
*/
3.12 枚举
- 枚举的功能类似于 字面量类型 + 联合类型 组合的功能,也可以 表示一组明确的可选值。
- 枚举 :
- 定义一组 命名常量;
- 使用
enum
关键字定义枚举; - 他描述一个值,该值可以是这些命名常量中的一个;
tsx
enum Direction { Up, Down, Left, Right }
function changeDirection(direction: Direction) {
console.log(direction);
}
- 🔺 注意:
- 使用
enum
关键字定义枚举; - 约定枚举名称、枚举中的值以 大写字母开头;
- 枚举中的多个值之间通过
,
(逗号)分隔; - 定义好枚举后,直接使用 枚举名称 作为 类型注解;
- 使用
- 访问枚举成员 :
- 类似于JS中的对象,直接通过
.
点语法访问枚举成员;
- 类似于JS中的对象,直接通过
3.12.1 数字枚举
- 枚举成员是有值的,默认为:从0开始递增的数值;
- 数字枚举:枚举成员 为 数字 的 枚举;
- 当然,也可以给枚举中的成员初始化值;
tsx
// enum Direction { Up, Down, Left, Right }
// function changeDirection(direction: Direction) {
// console.log(direction);
// }
// enum Direction {
// Up,
// Down,
// Left,
// Right
// }
// Down = 11, Left = 12, Right = 13
// enum Direction {
// Up = 10,
// Down,
// Left,
// Right
// }
enum Direction {
Up = 2,
Down = 4,
Left = 8,
Right = 16
}
function changeDirection(direction: Direction) {
console.log(direction);
}
// 访问 枚举成员
changeDirection(Direction.Up);
changeDirection(Direction.Down);
changeDirection(Direction.Left);
changeDirection(Direction.Right);
3.12.2 字符串枚举
- 字符串枚举 :枚举成员 的 值 是 字符串;
- 🔺 注意 :
- 字符串枚举没有自增长行为,因此,字符串枚举 的 每个成员 必须有 初始值;
tsx
// 字符串枚举
enum Direction {
Up = 'UP',
Down = 'Down',
Left = 'Left',
Right = 'Right'
}
3.12.3 枚举的特点及原理
- 枚举是TS为数不多的非JavaScript类型级扩展(不仅仅是类型)的特征之一
- 其他类型仅仅被当作类型,而枚举不仅用做类型,还提供值(枚举成员都是有值的)
- 也就是说,其他的类型都会在编译为JS代码时自动移除,但是,枚举类型会被编译为JS代码
- 说明:
- 枚举与前面讲到的字面量类型+联合类型组合的功能类似,都用来表示一组明确的可选值列表
- 一般情况下,推荐使用字面量类型+联合类型组合的方式,因为相比枚举,这种方式更加直观、简洁、高效
3.13 ❌ any 类型
- 不推荐使用
any
类型; - 作用 :
- 变量被注解为
any
类型之后,TS会忽略类型检查,错误的类型赋值不会报错,也不会有任何提示;
- 变量被注解为
- 隐式具有any类型的情况:
- 声明变量不提供类型也不提供默认值;
- 函数参数不加类型;
- 注意 :
any
使用的越多,程序可能出现的漏洞越多,因此不推荐使用any
类型,尽量避免;
3.14 泛型(Generics)
- 概念:
- 是指在定义接口、函数等类型的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性,使用泛型可以复用类型并且让类型更加灵活;
3.14.1 泛型接口、泛型别名
-
语法 :
- 泛型接口:
- 在接口类型的名称后面使用
<T>
既声明一个泛型参数,接口里面的其他成员都能使用该参数的类型;
- 在接口类型的名称后面使用
- 泛型别名:
- 在类型别名
type
的后面使用<T>
即可声明一个泛型参数,接口里的其他成员都能使用该参数的类型;
- 在类型别名
ts// 泛型接口 ✅ interface 类型名称<T> {} // 泛型别名 ❌ type 类型名称<T> = xxx
- 一般泛型名,是一个字母,大写;
- 泛型接口:
-
通用思路 :
- 找到 可变的类型部分 通过泛型
<T>
抽象为泛型参数(定义参数); - 再使用泛型的时候,把 具体类型传入到泛型参数位置(传参);
- 找到 可变的类型部分 通过泛型
-
注意 :
- 泛型参数可以有多个;
-
代码展示:
ts// 定义泛型接口 interface ResData<T> { code: number; msg: string; data: T; } // 定义具体类型 interface User { name: string; age: number; gender: string; } type UserInfo = ResData<User[]>; // 使用泛型并传入具体类型 // let userData: UserInfo = { let userData: ResData<User[]> = { code: 200, msg: "success", data: [ { name: "小Q", age: 24, gender: "女" } ] }; // 定义具体类型 interface Goods { id: number; goods_name: string; price: number; url: string; } type GoodInfo = ResData<Goods>; // 使用泛型并传入具体类型 // let goodsData: GoodsInfo = { let goodsData: ResData<Goods> = { code: 200, msg: "success", data: { id: 123, goods_name: "shuiGuo", price: 12, url: "www.baidu.com" } };
3.14.2 泛型函数
-
语法 :
- 在 函数名称 后面使用
<T>
即可声明一个泛型参数,整个函数中(参数、返回值、函数体、变量)都可以使用该参数的泛型;
tsfunction fn<T>() {}
- 在 函数名称 后面使用
-
代码展示:
ts// 需求:设置一个函数 creatArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值(多种类型) function createArray<T>(length: number, defVal: T): T[] { const arr = []; for (let i = 0; i < length; i++) { arr[i] = defVal; } return arr; } console.log(createArray<number>(5, 100));
3.14.3 泛型约束
-
作用 :
- 泛型的特点就是灵活不确定,有些时候泛型函数的内部需要 访问一些特定类型的数据才有的属性,此时会有类型错误,需要通过泛型约束解决;
-
使用关键字
extends
实现泛型约束; -
代码展示:
ts// 泛型约束 interface lengthObj { length: number; } function logLen<T extends lengthObj>(obj: T) { console.log(obj.length); } // 传参的时候,必须满足 lengthObj 类型 logLen<lengthObj>({ length: 8 }); logLen<lengthObj>([1]); logLen<lengthObj>("hello ts"); logLen<lengthObj>(100); // 报错:类型 number 的参数不能赋值给 lengthObj 的参数
3.15 typeof 运算符
- TS中的
typeof
操作符:可以在类型上下文中引用变量或属性的类型(类型查询) - 使用场景:根据已有变量的值,获取该值的类型,来简化类型书写
tsx
说明:
- 使用
typeof
操作符来获取变量p的类型,结果与第一种(对象字面量形式的类型)相同 typeof
出现在 类型注解的位置 (参数名称的冒号后面 ) 所处的环境就在类型上下文(区别于JS代码)- ⚠ 注意:
typeof
只能用来查询 变量或属性的类型,无法查询其他形式的类型(比如:函数调用的类型)