目录
- 引入
- 认识
- 特点
- 安装使用
- 变量
- 声明
- 类型推导
- JS 和 TS 共有类型
- number类型
- boolean类型
- string类型
- Array类型
- null和undefined类型
- object类型
- symbol类型
- 对象类型
- 函数类型
- 可选和只读
- type 和 interface
- 索引签名
- 类型断言
- 非空类型断言
- 类型缩小
- 严格赋值检测现象
- TS 新增类型
- 字面量类型
- any类型
- unknown类型
- void类型
- never类型
- tuple类型
- 联合类型
- 交叉类型
- 枚举类型
- 泛型
- 映射类型
- 条件类型
- 类型体操
- 模块-声明-配置
引入
随着近几年前端领域的快速发展,让JavaScript
迅速被普及和受广大开发者的喜爱,借助于JavaScript
本身的强大,也让使用JavaScript
开发的人员越来越多,JavaScript
正在慢慢变好,但是直到今天,JavaScript
在类型检测上依然是毫无进展
类型问题:
-
去实现一个核心类库时,如果没有类型约束,那么需要对别人传入的参数进行各种验证来保证代码的容错率
-
去调用别人的函数,对方没有对函数进行任何的注释,只能去看里面的逻辑来理解这个函数需要传入什么参数, 返回值是什么类型
-
如果可以给
JavaScript
加上很多限制,在开发中就可以很好的避免这样的问题了
为了弥补JavaScript
类型约束上的缺陷,很多公司推出了自己的方案:
2014
年,Facebook
推出了flow
来对JavaScript
进行类型检查- 同年,
Microsoft
微软也推出了TypeScript1.0
版本
TypeScript
使用率:
-
Vue2.x
的时候采用的就是flow
来做类型检查 -
Vue3.x
已经全线转向TypeScript
,98.3%使用TypeScript
进行了重构 -
Angular
在很早期就使用TypeScript
进行了项目重构并且需要使用TypeScript
来进行开发 -
最流行的编辑器
VSCode
也是使用TypeScript
来完成的 -
在
React
中已经使用的ant-design
的UI
库,也大量使用TypeScript
来编写
学习TypeScript
不仅仅可以为我们的代码增加类型约束,而且可以培养前端程序员具备类型思维
认识
TypeScript
在GitHub
和官方上对自己的定义:
-
GitHub
说法:TypeScript is a superset of JavaScript that compiles to clean JavaScript output
-
TypeScript
官网:TypeScript is a typed superset of JavaScript that compiles to plain JavaScript
-
翻译:
TypeScript
是拥有类型的JavaScript
超集,它可以编译成普通、干净、完整的JavaScript
代码
特点
-
始于
JavaScript
,归于JavaScript
-
使用现有的
JavaScript
代码,包括流行的JavaScript
库,并从JavaScript
代码中调用TypeScript
代码 -
TypeScript
可以编译出纯净、 简洁的JavaScript
代码,并且可以运行在任何浏览器上、Node.js
环境中和任何支持ECMAScript3
(或更高版本)的JavaScript
引擎中
-
-
TypeScript
是一个强大的工具,用于构建大型项目-
在语言层面上,不仅仅增加了类型约束,而且包括一些语法的扩展,比如枚举类型(
Enum
)、元组类型(Tuple
)等 -
类型允许
JavaScript
开发者在开发JavaScript
应用程序时使用高效的开发工具和常用操作比如静态检查和代码重构 -
类型是可选的,类型推断让一些类型的注释使你的代码的静态验证有很大的不同。类型让你定义软件组件之间的接口和洞察现有
JavaScript
库的行为
-
-
拥有先进的
JavaScript
-
JavaScript
所拥有的特性,TypeScript
全部都是支持的,并且它紧随ECMAScript
的标准 -
TypeScript
在实现新特性的同时,总是保持和ES
标准的同步甚至是领先 -
并且
TypeScript
最终会被编译成JavaScript
代码,所以并不需要担心它的兼容性问题,在编译时也可以不借助于Babel
这样的工具
-
安装使用
-
TypeScript
的环境安装依赖Node
,先保证电脑上有Node
和NPM
环境 -
npm install typescript -g
:安装 -
tsc --version
:查看版本 -
项目通常使用
webpack
配置本地的TypeScript
编译环境和开启一个本地服务,可以直接运行在浏览器上,这个在webpack
中学习 -
我们练习中就简单使用,先写
ts
文件(最后要写export {}
是用来声明一个模块的,告诉TypeScript
当前文件是一个模块,不是一个全局脚本文件,避免命名冲突) -
然后执行
tsc 文件名
编译成js
代码(编译后的代码要把exports
代码注释),在html
引入js
文件在浏览器查看结果
变量
声明
在TypeScript
中定义变量需要指定标识符的类型
-
声明了类型后
TypeScript
就会进行类型检测,声明的类型可以称之为类型注解(Type Annotation
) -
var/let/const 标识符: 数据类型 = 赋值
类型推导
有时候为了方便并不会在声明每一个变量时都写上对应的数据类型,TypeScript
会在一个变量第一次赋值时,根据后面的赋值内容的类型来推断出变量的类型
- 如果是
const
变量,赋值是一个常量字面量,它会推导为字面量类型。如果是let
,则推导为更宽泛的类型,如number
、string
,赋值为不同类型还是会报错let message = 'hello ts' // string类型 message = 123 // 会报错 不能将类型“number”分配给类型“string” let flag = true // boolean类型 const age = 18 // 字面量
JS 和 TS 共有类型
number类型
-
数字类型是我们开发中经常使用的类型,
TypeScript
和JavaScript
一样,不区分整数类型(int
)和浮点型(double
),统一为number
类型 -
ES6
新增了二进制和八进制的表示方法,而TypeScript
也是支持二进制、八进制、十六进制的表示
let num: number = 10
num = 18
num = 18.8
num = 100 // 十进制
num = 0b110 // 二进制
num = 0o555 // 八进制
num = 0xf23 // 十六进制
boolean类型
boolean
类型只有两个取值:true
和false
let flag: boolean = true
flag = false
flag = 20 > 30
string类型
string
类型是字符串类型,可以使用单引号或者双引号表示,也支持ES6
的模板字符串来拼接变量和字符串
let message: string = 'hello'
let n: string = 'ts'
message = `hello ${n}`
Array类型
数组类型的定义有两种方式: 下面都表示数组元素必须是string
Array<string>
string[]
let arr1: string[] = ['abc','cba']
let arr2: Array<string> = ['cba','abc']
arr1.push('ddd')
arr2.push('eee')
arr1.push(123) // 报错:Argument of type 'number' is not assignable to parameter of type 'string'
arr2.push(true) // 报错: Argument of type 'boolean' is not assignable to parameter of type 'string'
null和undefined类型
在 JavaScript
中,undefined
和 null
是两个基本数据类型。 在TypeScript
中,它们各自的类型也是undefined
和null
,也就意味着它们既是实际的值,也是自己的类型
let nu: null = null
nu = {} // Type '{}' is not assignable to type 'null'
let un: undefined = undefined
un = 0 // Type '0' is not assignable to type 'undefined'
object类型
-
object
描述的是所有非原始值的类型(即不包括string
、number
、boolean
、symbol
、null
和undefined
) -
使用
object
类型时,无法直接访问属性,因为TypeScript
并不知道对象的具体结构
let obj: object = { name: "John" };
console.log(obj.name); // 错误:属性 'name' 不存在于 'object' 类型上
obj = { key: "value" }; // 正确
obj = [1, 2, 3]; // 正确
obj = function() {}; // 正确
obj = "string"; // 错误,不能将 'string' 赋值给 'object'
symbol类型
Symbol
是一种基本数据类型,它代表独一无二且不可变的值。它最常用于对象属性的键值,保证每个 Symbol
都是唯一的,防止属性名冲突
let sym1: symbol = Symbol();
let sym2: symbol = Symbol("description");
console.log(sym1 === sym2); // false,两个 Symbol 值是唯一的
对象类型
具体学习这篇文章:待后面补充
函数类型
具体学习这篇文章:待后面补充
可选和只读
-
可选:可选属性意味着该属性可以有,也可以没有,属于非必须的属性。如果没有赋值,这个属性的值为
undefined
,在属性的后面添加一个?
表示let bar: {name: string, age: number} = { name: 'obj', age: 18, } function getInfo(data: {name: string, age: number, height?: number}) { console.log(data) } getInfo(bar) // 如果height不是可选的就会报错说bar缺少属性
-
只读:只读属性意味着该属性一旦赋值之后就无法修改。通常用于防止对象的某些属性在对象初始化后被改变,在属性的前面加
readonly
表示function getInfo(data: {name: string, readonly age: number, height?: number}) { console.log(data.age) data.age = 18 // 会报错 }
-
可选可以结合只读
type Person = { readonly id?: number; // 可选且只读属性 name: string; }; const person: Person = { name: "Alice" }; // 合法,因为 id 是可选的 const personWithId: Person = { id: 1, name: "Bob" }; // 错误,因为 id 是只读属性,不能修改 // personWithId.id = 2; // Error: Cannot assign to 'id' because it is a read-only property.
type 和 interface
-
type 新类型名 = 现有类型
:定义类型别名,通过类型别名,可以将复杂的类型定义抽象为一个更简单的名字,并在代码中反复使用;可以用于基础类型、对象类型、联合类型、数组、函数等各种类型type UserType = { name: string; age?: number; readonly height: number }; let user: UserType = { name: "Alice", height: 188, };
-
interface
接口:是一种用于定义对象、函数、类等结构的方式interface IUser { name: string; age?: number; readonly height: number } let user: IUser = { name: "Alice", height: 188, };
-
两者区别:
-
区别一:
type
类型使用范围更广,而interface
主要用于定义对象的形状 -
区别二:同名接口可以合并(声明合并),如果两个地方声明了同名的接口,
TypeScript
会将它们的成员自动合并到一个接口中interface ILocal { x: number y: number } interface ILocal { z: number } const local: ILocal = { // 会合并,必须包含x,y,z x: 100, y: 200, z: 300 }
-
区别三:接口可以继承一个或多个其他接口,使得多个接口可以共享相同的属性和方法定义
interface IAdult { name: string, age: number } interface IWorker { working: () => void } interface ICoder extends IAdult, IWorker { eatting: () => void } const student: ICoder = { name: 'coder', age: 16, working() { console.log('working') }, eatting() { console.log('eatting') } }
-
区别四:类可以通过
implements
关键字来实现接口,保证类中定义了接口所要求的所有属性和方法,具体学习这篇文章:待后面补充
-
索引签名
具体学习这篇文章:待后面补充
类型断言
类型断言(Type Assertions
)用于明确地告诉编译器某个值的类型,而不是让编译器自动推断类型,类型断言不会做类型转换,它只是在编译时进行静态检查,帮助你绕过编译器的类型检查限制
- 语法:
-
尖括号语法:
let someValue: any = "this is a string"; let strLength: number = (<string>someValue).length;
-
as
语法: 在使用JSX
的时候,不能使用尖括号语法,必须使用as
语法let someValue: any = "this is a string"; let strLength: number = (someValue as string).length;
-
- 使用时机:
-
当 TypeScript 无法自动推断类型时: 比如使用第三方库返回的
any
类型数据,或者处理一些复杂的联合类型时,类型断言可以帮你明确告诉TypeScript
某个值的具体类型 -
在联合类型中确定某个具体类型: 在联合类型中,你可以使用类型断言将值断言为更具体的类型
-
DOM 元素类型断言: 在访问
DOM
元素时,TypeScript
可能无法准确推断类型。你可以使用类型断言来告诉TypeScript
你知道元素的确切类型,提示方法更友好const inputElement = document.getElementById('input') as HTMLInputElement; inputElement.value = "Hello, World!";
-
- 限制:
-
类型断言并不会改变数据的实际类型,而是让 TypeScript 编译器“信任”你给出的类型。因此,错误的类型断言可能导致运行时错误
let someValue: any = "hello"; let num: number = someValue as number; // 这不会在编译时报错,但会导致运行时错误
-
类型断言不能断言为不相关的类型,例如你不能将一个
string
类型断言为number
类型let someValue: any = "hello"; let num: number = someValue as number; // 无效的断言,编译时不会报错,但运行时可能有问题
-
非空类型断言
允许开发者告诉编译器某个表达式不会为 null
或 undefined
,它通过在表达式后面加上 !
操作符实现
-
使用:
-
基本使用:如果某个
DOM
元素可能为null
,但我们知道在使用时它肯定已经存在,可以使用非空断言const element = document.getElementById("myElement"); console.log(element!.innerHTML); // 使用 `!` 断言告诉 TypeScript 这里 `element` 不会是 `null`
-
函数中的非空断言: 假设你有一个函数返回可能是
null
或undefined
的值,但你确定在某个情况下这个函数一定会返回一个有效值function getValue(): string | undefined { return "Hello"; } const value = getValue(); console.log(value!.toUpperCase()); // 使用 `!` 断言忽略 `undefined` 检查
-
联合类型中的非空断言: 对于联合类型中的
null
或undefined
,你也可以使用非空断言function processValue(value: string | null) { console.log(value!.toUpperCase()); // 告诉编译器 value 绝对不会为 null } processValue("Hello"); // 安全 processValue(null); // 会在运行时抛出错误,因为实际上值为 null
-
-
注意:
-
非空断言不会在运行时进行检查:非空断言只是为了告诉编译器在这个地方忽略
null
或undefined
的检查,但如果你使用非空断言的地方值实际为null
或undefined
,仍然会在运行时抛出错误 -
应谨慎使用:过度使用非空断言可能隐藏代码中的潜在错误。只有在你 非常确定 某个值不会为
null
或undefined
时,才应该使用这个操作符
-
类型缩小
类型缩小通过各种类型守卫来帮助 TypeScript
更精确地推断出变量的类型,从而提高代码的安全性和开发体验。主要缩小方式包括:typeof
、instanceof
、in
、平等缩小(===、!==
)等等
-
typeof
:function printID(id: number | string) { if (typeof id === "string") { console.log(id.length, id.split(" ")) } else { console.log(id) } }
-
平等缩小(
===、!==
):type localType = 'up' | 'down' | 'left' | 'right' function getLocal(local: localType) { if(local === 'up') { console.log('向上走') } }
-
instanceof
:function formatDate(date: string | Date) { // if(typeof date === 'string') { // console.log(date) // }else { // console.log(date.getTime()) // } if(date instanceof Date) { // 判断date是不是Date的实例 console.log(date.getTime()) }else { console.log(date) } }
-
in
操作符:interface ISwim { swim: () => void } interface IRun { run: () => void } function move(animal: ISwim | IRun) { if ("swim" in animal) { animal.swim() } else if ("run" in animal) { animal.run() } }
严格赋值检测现象
对于对象的字面量赋值,在TypeScript
中有一个非常有意思的现象我们看下面例子,在例子中发现换一种赋值的方式多余的属性不会报错
type TTest = {name: string, age: number, height: number}
const tt ={
name: 'tt',
age: 28,
height: '188',
}
const test1: TTest = tt // 会报错没问题
interface ITest {
name: string,
eatting: () => void
}
const it = {
name: 'it',
age: 18,
eatting: function(){}
}
// 方式一
const test2: ITest = {
name: 'it',
age: 18, // 多的会报错
eatting: function(){}
}
// 方式二
const test3: ITest = it // 多了age属性不会报错
上面现象解释引入TypeScript
成员在GitHub
的issue
中的回答:
翻译理解一下:
-
每个对象字面量最初都被认为是 " 新鲜的(
fresh
)" -
当一个新的对象字面量分配给一个变量或传递给一个非空目标类型的参数时,对象字面量指定目标类型中不存在的属性是错误的
-
当类型断言或对象字面量的类型扩大时,新鲜度会消失
TS 新增类型
字面量类型
它允许将变量的类型限定为特定的值,字面量类型可以是字符串、数字、布尔值、null
、undefined
、bigint
、symbol
等,通过字面量类型,你可以让变量的值更加精确
-
使用:
-
单独使用,使用
const
定义变量时,类型推测就为字面量类型const abc = 'abc' // 这时abc就是为‘abc’的字面量类型 const data = { // 这时data就是为对象的字面量类型 url: 'http://localhost:8080', method: 'post' }
-
字符串字面量类型结合联合类型
let direction: "left" | "right" | "up" | "down"; direction = "left"; // 正确 direction = "right"; // 正确 direction = "forward"; // 错误,"forward" 不在定义的字面量类型之中
-
数字字面量类型结合联合类型
let option: 1 | 2 | 3; option = 1; // 正确 option = 4; // 错误,因为 4 不在数字字面量类型的范围内
-
布尔字面量类型结合联合类型
let isOpen: true | false; isOpen = true; // 正确 isOpen = false; // 正确
-
-
推理:
/* const data = { url: 'http://localhost:8080', method: 'post' } type methodType = 'get' | 'post' function request(url: string, method: methodType) { console.log(method) } request(data.url, data.method) */ /* 上面的 data.method 会报错: Argument of type 'string' is not assignable to parameter of type 'methodType' 因为 data.method 推测出的是string类型,不能赋值给字面量类型 所以我们要明确写明 data.method 是个字面量类型 解决方法: 一:类型断言明确告诉它data.method为post字面量类型 request(data.url, data.method as ’post‘) 二: const data = { url: 'http://localhost:8080', method: 'post' } as const */ type methodType = 'get' | 'post' // 方式一 const data1 = { url: 'http://localhost:8080', method: 'post' } function request1(url: string, method: methodType) { console.log(method) } request1(data1.url, data1.method as 'post') // 类型断言data.method为post字面量类型 // 方式二 /* as const: 是一个断言操作符,它用于将一个对象或数组的所有属性或元素转换为字面量类型 相当于变成了常量对象 const data2: { readonly url: 'http://localhost:8080', readonly method: 'post' } = { url: 'http://localhost:8080', method: 'post' } */ const data2 = { url: 'http://localhost:8080', method: 'post' } as const function request2(url: string, method: methodType) { console.log(method) } request2(data2.url, data2.method)
-
应用:
-
参数和请求方法限制:字面量类型通常与联合类型一起使用,用于限制函数参数的值只能是特定的字面量
-
状态管理:在状态管理中,字面量类型可以用来确保状态值总是一个指定的值
-
配置项限制:当某个配置项需要限定特定值时,可以使用字面量类型
-
any类型
在某些情况下,确实无法确定一个变量的类型,并且可能它会发生一些变化,这个时候可以使用any
类型
-
可以对
any
类型的变量进行任何的操作,包括获取不存在的属性、方法 -
给一个
any
类型的变量赋值任何的值,比如数字、字符串的值 -
对于某些情况的处理过于繁琐不希望添加规定的类型注解,或者在引入一些第三方库时,缺失了类型注解,这个时候我们可以使用
any
let a: any = '123'
a = 123
a = null
a = undefined
a = true
let aArr: any[] = ['123', 123, true, null]
unknown类型
unknown
是TypeScript
中比较特殊的一种类型,它用于描述类型不确定的变量
- 和
any
类型有点类似,但是unknown
类型的值上做任何事情都是不合法的
let a: any = '123'
a = 123
a = null
a = undefined
a = true
console.log(a.length) // 不会报错
let uk: unknown = '123'
uk = 123
uk = null
uk = undefined
uk = true
console.log(uk.length) // 会报错 'uk' is of type 'unknown'
if(typeof uk == 'string') { // 只有当类型范围缩小时再操作才不会报错
console.log(uk.length)
}
void类型
void
通常用来指定一个函数是没有返回值的,那么它的返回值就是void
类型
-
当基于上下文的类型推导(
Contextual Typing
)推导出返回类型为void
的时候,并不会强制函数一定不能返回内容,可以返回任何类型 -
如果明确写了函数返回值为
void
类型时,函数只可以返回undefined
-
void
变量可以赋值undefined
,但除了函数返回之外,void
通常不被使用
let unused: void = undefined; // 虽然可以赋值 undefined,但除了函数返回之外,void 通常不被使用
function foo1() { // void类型
console.log(123)
}
function foo2(): void {
console.log(123)
return undefined // 只能返回undefined,返回其他值会报错
}
never类型
never
类型表示那些永远不会存在值的类型。这种类型通常出现在以下几种情况下:
-
函数永远不会返回值: 当一个函数永远不会成功执行到结束,它会抛出错误或导致程序退出,这样的函数返回类型是
never
。比如死循环或者抛出异常的函数 -
不可达的代码: 当代码逻辑到达某个永远不可能发生的分支时,可以用
never
来标记这类情况
function throwError(message: string): never {
throw new Error(message);
}
function infiniteLoop(): never {
while (true) {
console.log("This will run forever");
}
}
function checkType(key: string | number | boolean){
switch (typeof key) {
case 'string':
console.log(key.length)
break;
case 'number':
console.log(key)
break;
// case 'boolean': // 不加此代码就会报错 Type 'boolean' is not assignable to type 'never'
// console.log(!key)
// break;
default:
const type: never = key // 那么这么写的意义何在?在扩展工具时,检测出一些没有处理的case,直接报错 Type 'boolean' is not assignable to type 'never'
}
}
tuple类型
tuple
是元组类型,很多语言中也有这种数据类型,比如Python、Swift
等
tuple
和数组有什么区别:
-
数组中通常建议存放相同类型的元素,不同类型的元素是不推荐放在数组中(可以放在对象或者元组中)
-
元组中每个元素都有自己特定的类型,根据索引值获取到的值可以确定对应的类型
-
tuple
通常可以作为返回的值,在使用的时候会非常的方便 -
TypeScript
中的元组继承了数组的行为。在JavaScript
中,数组是动态的,元素可以随时增加或删除。为了兼容这一点,TypeScript
允许通过数组方法往元组中动态添加元素 -
TypeScript
的元组会检查方法传入的参数类型是否与元组的元素类型兼容。只要你添加的元素类型符合元组定义中的类型,就不会有类型错误
let tu: [string, number, boolean, null?] = ['123', 123, true]
let tu0 = tu[0] // tu0就是string类型
tu.push(null)
tu.push('123')
tu.push({}) // 会报错因为元组中没有定义对象
// 在函数中使用元组类型是最多的(函数的返回值)
function useState(initialState: number): [number, (newValue: number) => void] {
let stateValue = initialState
function setValue(newValue: number) {
stateValue = newValue
}
return [stateValue, setValue]
}
const [count, setCount] = useState(10)
console.log(count)
setCount(100)
联合类型
联合类型是由两个或者多个其他类型组成的类型,使用 |
表示,表示可以是这些类型中的任何一个值,联合类型中的每一个类型被称之为联合成员(union's members
)
-
传入给一个联合类型的值只要保证是联合类型中的某一个类型的值即可
-
使用时需要进行类型缩小,
TypeScript
可以根据缩小的代码结构,推断出更加具体的类型 -
可以和字面量类型结合使用
let union: boolean | string = '123'
union = true
function handleUnion(un: boolean | string){
console.log(un.length) // 报错
if(typeof un === 'string') { // 类型缩小
console.log(un.length)
}else {
console.log(un)
}
}
handleUnion(union)
// 结合字面量类型
type localType = 'up' | 'down' | 'left' | 'right'
function getLocal(local: localType) {
if(local === 'up') {
console.log('向上走')
}
console.log(local.length)
}
getLocal('down')
getLocal(123) // 会报错
交叉类型
交叉类型使用 &
符号表示需要满足多个类型的条件
let sn: string & number // 这种值肯定是没有的,没有意义
// 交叉类型应用
type personType = { name: string, running: () => void }
interface IPerson {
age: number,
jumping: () => void
}
const info: personType & IPerson = { // 将多个对象的属性合并
name: 'info',
age: 38,
running:() => {},
jumping:() => {}
}
function getPerson (person: personType & IPerson) {
console.log(person)
}
getPerson(info)
枚举类型
枚举其实就是将一组可能出现的值,一个个列举出来,定义在一个类型中,这个类型就是枚举类型,枚举允许开发者定义一组命名常量,常量可以是数字、字符串类型
-
数字枚举:是最常见的枚举类型,枚举成员的值默认是从
0
开始递增的,具有反向映射的特性,可以通过枚举的值来获取枚举成员的名字enum Direction { Up, // 0 Down, // 1 Left, // 2 Right // 3 } let dir: Direction = Direction.Up; console.log(dir); // 输出: 0 enum Direction { Up = 1, // 1 Down, // 2 Left, // 3 Right // 4 } console.log(Direction.Up); // 输出: 1 console.log(Direction[1]); // 输出: "Up" ,反向取值
-
字符串枚举:每个成员必须显式地设置字符串值,并且不会进行自动递增,不具备反向映射特性
enum Direction { Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT" } let dir: Direction = Direction.Up; console.log(dir); // 输出: "UP"
-
常量枚举:在需要性能优化的场景下,你可以使用
const enum
来声明常量枚举,会在编译时被完全移除,使用枚举成员的地方会被替换成实际的值const enum Direction { Up, Down, Left, Right } let dir: Direction = Direction.Up; console.log(dir); // 输出: 0
-
枚举成员:分为常量成员(constant member)和计算成员(computed member)
-
常量成员是在编译时计算出值的,或者从数字常量初始化的枚举
-
计算成员是在运行时计算其值的
enum FileAccess { None, Read = 1 << 1, // 常量成员 Write = 1 << 2, // 常量成员 ReadWrite = Read | Write, // 常量成员 G = "123".length // 计算成员 }
-
-
枚举本身可以作为一种类型来使用
enum Direction { Up, Down, Left, Right } function move(direction: Direction) { console.log(direction); } move(Direction.Left); // 输出: 2
泛型
具体学习这篇文章:待后面补充
映射类型
具体学习这篇文章:待后面补充
条件类型
具体学习这篇文章:待后面补充
类型体操
具体学习这篇文章:待后面补充
模块-声明-配置
具体学习这篇文章:待后面补充