TypeScript 增加了一些 JavaScript 没有的语法特性,以提高代码的可维护性和可读性。下面是 TypeScript 的一些主要语法特性:
基本类型
类型 | 描述 | 示例代码 |
---|
boolean | 布尔值类型,只有 true 和 false | let isDone: boolean = false; |
number | 数值类型,包括整数和浮点数 | let count: number = 10; |
string | 字符串类型 | let name: string = "John"; |
Array | 数组类型,可以指定元素类型 | let list: number[] = [1, 2, 3]; |
Tuple | 元组类型,表示固定数量和类型的数组 | let tuple: [string, number] = ["hello", 10]; |
Enum | 枚举类型,用于定义一组命名常量 | enum Color { Red, Green, Blue } |
any | 任意类型,可用于绕过类型检查 | let notSure: any = 4; notSure = "maybe a string"; |
void | 无返回值类型,通常用于函数的返回值类型 | function warnUser(): void { console.log("Warning!"); } |
null | 表示值为 null | let n: null = null; |
undefined | 表示值为 undefined | let u: undefined = undefined; |
never | 表示不会出现的值类型,通常用于抛出异常或无限循环的函数 | function error(message: string): never { throw new Error(message); } |
object | 非原始类型,包括对象、数组、函数等 | let obj: object = { name: "John" }; |
unknown | 未知类型,需要进行类型检查后才能使用 | let notSure: unknown = 4; if (typeof notSure === "number") { let value: number = notSure; } |
Function | 函数类型,用于定义函数的参数和返回值类型 | let myAdd: (x: number, y: number) => number = function(x, y) { return x + y; }; |
Interface | 接口类型,用于定义对象的结构 | interface Person { firstName: string; lastName: string; } |
Type Alias | 类型别名,用于给类型起一个新名字 | type Name = string; |
Union | 联合类型,表示可以是多种类型之一 | `let value: string |
Intersection | 交叉类型,将多个类型合并为一个类型 | type Pet = Bird & Fish; |
Literal | 字面量类型,使用具体的值作为类型 | `let literal: “hello" |
Type Assertion | 类型断言,用于手动指定一个值的类型 | let someValue: any = "this is a string"; let strLength: number = (someValue as string).length; |
Generics | 泛型,允许定义时不指定具体类型,而在使用时再指定 | function identity<T>(arg: T): T { return arg; } |
Readonly | 只读属性,用于防止属性被修改 | interface Person { readonly id: number; name: string; } |
Optional | 可选属性,用于定义可选的属性 | interface Person { firstName: string; lastName?: string; } |
Namespace | 命名空间,用于组织代码,避免命名冲突 | namespace Validation { export function validate() { /* ... */ } } |
Module | 模块,用于将代码分割成独立的文件和块 | import { add } from "./math"; |
空安全
在 TypeScript 中,空安全(null safety)是一种用于处理 null
和 undefined
值的机制,确保代码在运行时不会因为访问 null
或 undefined
值而抛出错误。TypeScript 提供了多种方法来处理可能为空的值,包括可选链、空值合并运算符、类型守卫等。
可选属性
在接口或类型中,可以使用 ?
表示属性是可选的,意味着它可能不存在或为 undefined
。
可选链(Optional Chaining)
可选链运算符(?.
)允许安全地访问对象的属性,即使该属性可能为 null
或 undefined
。如果属性不存在,表达式会短路并返回 undefined
。
空值合并运算符(Nullish Coalescing)
空值合并运算符(??
)用于提供默认值,当左侧的操作数为 null
或 undefined
时,返回右侧的操作数。
类型守卫(Type Guards)
类型守卫用于检查和处理 null
和 undefined
值,确保类型安全。
使用 typeof
使用 ==
或 ===
非空断言操作符(Non-null Assertion Operator)
非空断言操作符(!
)用于断言一个值不为 null
或 undefined
,告诉 TypeScript 编译器跳过类型检查。请谨慎使用,因为错误的断言可能导致运行时错误。
严格的空检查模式
在 tsconfig.json
中启用 strictNullChecks
选项,使得所有未明确指定为可选的类型默认不接受 null
或 undefined
。启用该选项后,TypeScript 会在编译时检查所有可能为空的情况。
实际案例
以下是一个实际案例,展示了如何使用空安全特性来处理可能为空的值:
枚举
在 TypeScript 中,枚举(Enum)是一种特殊的数据类型,允许开发者为一组相关值赋予友好的名称。枚举使代码更具可读性和可维护性。
枚举的定义
可以通过 enum
关键字定义枚举,枚举成员默认从 0 开始自动递增编号。
指定枚举成员的值
可以为枚举成员手动指定值:
反向映射
枚举还支持从值到名称的反向映射:
常量枚举
常量枚举通过 const enum
定义,它在编译时会被内联进生成的代码中,不会生成实际的枚举对象,提升性能:
异构枚举
枚举成员可以是不同类型的值(字符串或数字):
枚举用法示例
以下是枚举在实际应用中的一些示例:
接口
在 TypeScript 中,接口(Interface)是一种强类型约束,用于定义对象的结构。接口可以用于定义对象的属性、方法以及函数的形状。接口在 TypeScript 中是一个非常重要的特性,可以帮助你更好地组织代码和确保类型安全。
定义接口
下面是一个基本的接口定义示例:
可选属性
接口中的属性可以是可选的,使用 ?
来表示:
只读属性
接口中的属性可以是只读的,使用 readonly
关键字来表示:
函数类型
接口可以用于定义函数类型:
可索引类型
接口可以用于描述那些可以通过索引获取的类型:
类类型
接口可以用于强制一个类去符合某种契约:
继承接口
接口可以继承其他接口,从而可以将多个接口合并为一个接口:
混合类型
接口还可以描述那些既是函数又具有某些属性的对象:
接口扩展类
接口也可以扩展类:
类
在 TypeScript 中,类(Class)是面向对象编程的核心概念。类提供了一种将数据和功能封装在一起的方式。下面详细介绍 TypeScript 中类的使用方法。
类的基本定义
以下是一个简单的类定义示例:
继承
TypeScript 支持类的继承,通过 extends
关键字可以创建一个继承另一个类的新类:
公共、私有与受保护的修饰符
TypeScript 提供了 public
、private
和 protected
三种访问修饰符,用于控制类成员的可见性。
公共成员(public)
默认情况下,类的成员是公共的。
私有成员(private)
私有成员只能在类的内部访问。
受保护的成员(protected)
受保护的成员可以在类及其子类中访问。
Readonly 修饰符
readonly
修饰符用于将属性设置为只读,只能在初始化或构造函数中赋值。
存取器
可以通过 get
和 set
关键字定义访问器来控制对属性的访问。
静态属性
静态属性是类的属性,而不是实例的属性。使用 static
关键字定义。
抽象类
抽象类是不能被实例化的类,只能被继承。抽象类使用 abstract
关键字定义,可以包含抽象方法,这些方法必须在派生类中实现。
函数
在 TypeScript 中,函数是最基本的构建模块之一。TypeScript 允许定义多种类型的函数,以满足不同的需求。下面详细介绍 TypeScript 中函数的分类和使用方法。
函数声明
通过 function
关键字声明一个函数,这是最常见的函数定义方式。
函数表达式
通过将函数赋值给一个变量来定义函数,这种方式也很常见。
箭头函数
箭头函数提供了一种简洁的语法来定义函数,特别适用于回调函数和内联函数。
可选参数和默认参数
函数的参数可以是可选的,也可以有默认值。
可选参数
使用 ?
表示参数是可选的。
默认参数
给参数提供默认值,如果调用时未提供该参数,则使用默认值。
剩余参数
使用 ...
语法可以定义剩余参数,表示函数可以接受任意数量的参数。
函数重载
TypeScript 支持函数重载,即可以为同一个函数定义多个类型签名。
this 参数
在 TypeScript 中,可以使用 this
参数来明确指定 this
的类型。
函数类型
可以定义函数的类型,包括参数类型和返回值类型。
泛型
在 TypeScript 中,泛型(Generics)是一个强大的特性,允许开发者创建可重用的组件。这些组件不仅能处理一种数据类型,而是能处理多种数据类型,从而增强代码的灵活性和可重用性。泛型使得类型可以作为参数传递给类、接口和函数。
泛型函数
定义泛型函数时,使用尖括号 <>
来指定泛型类型变量。下面是一个简单的泛型函数示例:
泛型接口
可以使用泛型定义接口,从而使接口中的某些成员具有通用类型:
泛型类
泛型可以用于类的定义,使类中的成员具有通用类型:
泛型约束
可以对泛型类型变量进行约束,限制其类型范围:
使用类型参数在泛型约束中
在泛型约束中使用其他类型参数:
泛型默认类型
可以为泛型指定默认类型:
高级用法
泛型条件类型
TypeScript 还支持条件类型,可以基于类型做判断:
映射类型
映射类型允许将一个类型的属性转换为另一个类型的属性:
类型断言
类型断言可以手动指定一个值的类型(类似于类型转换):
模块和命名空间
在 TypeScript 中,模块和命名空间是用于组织代码的两种方式。它们都能帮助开发者避免命名冲突,提高代码的可维护性和可读性。下面详细介绍 TypeScript 中的模块和命名空间。
模块
模块是外部模块的实现方式,文件是模块的自然单元。每个模块都有自己的作用域,默认情况下文件中的所有内容都在模块的作用域内,其他模块无法访问。模块通过 import
和 export
关键字进行导入和导出。
导出模块
使用 export
关键字导出变量、函数、类或接口:
导入模块
使用 import
关键字从其他模块导入变量、函数、类或接口:
默认导出
一个模块可以有一个默认导出,使用 export default
语法:
导入默认导出时,可以使用任意名称:
命名空间
命名空间用于组织在一个全局作用域下的代码。与模块不同,命名空间主要用于在同一文件或多个文件中的逻辑分组,使用 namespace
关键字定义。
定义命名空间
嵌套命名空间
命名空间可以嵌套,用于更细粒度地组织代码:
命名空间合并
命名空间可以跨多个文件进行合并,通过 /// <reference path="..." />
指令引入。
区别和使用场景
- 模块:适用于将代码组织到独立的文件中,促进代码的可维护性和重用性。模块是 ES6 的标准,在现代 JavaScript 项目中更为推荐使用。
- 命名空间:适用于在一个全局作用域下组织代码,主要用于大型项目中的逻辑分组。命名空间更类似于传统的编程语言中的包或库,但在现代 TypeScript 开发中,建议尽量使用模块代替命名空间。
类型别名
类型别名(Type Aliases)是 TypeScript 中一种方便的方式,用于为复杂类型赋予一个简单的名称。类型别名可以用于基本类型、对象类型、联合类型、交叉类型等。类型别名使用 type
关键字来定义。
定义类型别名
类型别名可以用于简单类型:
对象类型别名
类型别名可以用于定义对象类型:
联合类型别名
类型别名可以用于定义联合类型:
交叉类型别名
类型别名可以用于定义交叉类型:
泛型类型别名
类型别名可以使用泛型来创建灵活的类型:
函数类型别名
类型别名可以用于定义函数类型:
可索引类型别名
类型别名可以用于定义可索引类型:
类型别名与接口的区别
类型别名和接口在某些情况下可以互换使用,但也有一些不同之处:
-
接口扩展:
接口可以通过 extends
关键字扩展其他接口或类型别名,而类型别名需要通过交叉类型来实现扩展。
-
实现类:
类可以实现接口,但不能实现类型别名。
-
联合类型和交叉类型:
类型别名可以定义联合类型和交叉类型,而接口不能直接定义这些类型。
交叉类型与联合类型
交叉类型(Intersection Types)和联合类型(Union Types)是 TypeScript 中的两个重要特性,它们可以用于构建更复杂的类型系统,提供更强大的类型检查能力。
交叉类型(Intersection Types)
交叉类型将多个类型合并为一个类型。新类型具有所有合并类型的成员。交叉类型使用 &
符号定义。
示例
在上述示例中,Manager
类型同时包含 Person
和 Employee
的所有属性。
联合类型(Union Types)
联合类型表示一个值可以是几种类型之一。联合类型使用 |
符号定义。
示例
在上述示例中,userId
可以是 number
或 string
类型。
交叉类型与联合类型的使用场景
交叉类型的使用场景
交叉类型通常用于将多个类型合并为一个类型,当一个对象需要具有多个类型的所有属性时很有用。
联合类型的使用场景
联合类型常用于一个值可以是几种类型之一的情况,尤其是在函数参数和返回值类型中。
类型保护
在使用联合类型时,通常需要进行类型检查以确保安全地使用值。TypeScript 提供了几种类型保护机制。
使用 typeof
typeof
运算符可以用来检查基本类型。
使用 instanceof
instanceof
运算符可以用来检查对象的类型。
使用自定义类型保护
可以定义类型谓词(type predicate)来创建自定义的类型保护。
工具泛型类
在 TypeScript 中,工具泛型类(Utility Types)是一些内置的类型,用于帮助开发者在类型系统中进行变换和处理。它们可以简化常见的类型操作,提高代码的可读性和维护性。
常见的工具泛型类
以下是 TypeScript 中一些常用的工具泛型类:
1. Partial<T>
将类型 T
的所有属性变为可选。
type Partial<T>
:这是在定义一个泛型类型 Partial
,它接受一个类型参数 T
。
{ [P in keyof T]?: T[P]; }
:这是一个映射类型,用于将 T
的所有属性变为可选属性。
keyof T
:提取类型 T
的所有键,返回一个联合类型。
[P in keyof T]
:通过遍历 T
的所有键 P
,构建一个新的类型。
T[P]
:获取类型 T
中键 P
对应的属性类型。
?
:将属性 P
变为可选属性。
2. Required<T>
将类型 T
的所有属性变为必选。
type Required<T>
:这是在定义一个泛型类型 Required
,它接受一个类型参数 T
。
{ [P in keyof T]-?: T[P]; }
:这是一个映射类型,用于将 T
的所有属性变为必选属性。
keyof T
:提取类型 T
的所有键,返回一个联合类型。
[P in keyof T]
:通过遍历 T
的所有键 P
,构建一个新的类型。
T[P]
:获取类型 T
中键 P
对应的属性类型。
-?
:移除属性 P
上的可选标记,使其成为必选属性。
3. Readonly<T>
将类型 T
的所有属性变为只读。
type Readonly<T>
:这是在定义一个泛型类型 Readonly
,它接受一个类型参数 T
。
{ readonly [P in keyof T]: T[P]; }
:这是一个映射类型,用于将 T
的所有属性变为只读属性。
keyof T
:提取类型 T
的所有键,返回一个联合类型。
[P in keyof T]
:通过遍历 T
的所有键 P
,构建一个新的类型。
T[P]
:获取类型 T
中键 P
对应的属性类型。
readonly
:将属性 P
标记为只读属性。
4. Record<K, T>
将类型 K
的所有属性的值变为类型 T
。
type Record<K extends keyof any, T>
:这是在定义一个泛型类型 Record
,它接受两个类型参数 K
和 T
。
K
代表对象的键的类型。
T
代表对象的值的类型。
K extends keyof any
约束 K
必须是 string
、number
或 symbol
类型,因为对象的键只能是这三种类型之一。
{ [P in K]: T; }
:这是一个映射类型,用于构建一个新的对象类型。
[P in K]
:遍历联合类型 K
中的所有键 P
。
T
:将键 P
的值类型设置为 T
。
5. Pick<T, K>
从类型 T
中选择一组属性 K
。
type Pick<T, K extends keyof T>
:这是在定义一个泛型类型 Pick
,它接受两个类型参数 T
和 K
。
T
代表源类型。
K
代表从 T
中选择的一组属性。
K extends keyof T
确保 K
是 T
中属性键的联合类型。
{ [P in K]: T[P]; }
:这是一个映射类型,用于构建一个新的对象类型,只包含 T
中键为 K
的属性。
[P in K]
:遍历联合类型 K
中的所有键 P
。
T[P]
:获取类型 T
中键 P
对应的属性类型。
6. Omit<T, K>
从类型 T
中剔除一组属性 K
。
type Omit<T, K extends keyof any>
:这是在定义一个泛型类型 Omit
,它接受两个类型参数 T
和 K
。
T
代表源类型。
K
代表要剔除的一组属性。
K extends keyof any
确保 K
是可以作为键的类型,即 string
、number
或 symbol
。
Pick<T, Exclude<keyof T, K>>
:这是类型构造的一部分,它通过以下步骤构建出新的类型:
keyof T
:提取类型 T
的所有键,形成一个联合类型。
Exclude<keyof T, K>
:从 keyof T
中剔除类型 K
,得到剩下的键的联合类型。
Pick<T, Exclude<keyof T, K>>
:从类型 T
中选择剩下的键,构建一个新的类型。
7. Exclude<T, U>
从类型 T
中剔除可以赋值给类型 U
的类型。
type Exclude<T, U>
:这是在定义一个泛型类型 Exclude
,它接受两个类型参数 T
和 U
。
T extends U ? never : T
:这是一个条件类型,用于剔除 T
中可以赋值给 U
的类型。
T extends U
:如果 T
可以赋值给 U
,则结果为 never
。
never
:表示不包含任何值的类型,用于剔除 T
中可以赋值给 U
的部分。
: T
:如果 T
不能赋值给 U
,则结果为 T
。
从类型 T
中提取可以赋值给类型 U
的类型。
type Extract<T, U>
:这是在定义一个泛型类型 Extract
,它接受两个类型参数 T
和 U
。
T extends U ? T : never
:这是一个条件类型,用于提取 T
中可以赋值给 U
的类型。
T extends U
:如果 T
可以赋值给 U
,则结果为 T
。
: never
:如果 T
不能赋值给 U
,则结果为 never
。
9. NonNullable<T>
从类型 T
中剔除 null
和 undefined
。
type NonNullable<T>
:这是在定义一个泛型类型 NonNullable
,它接受一个类型参数 T
。
T extends null | undefined ? never : T
:这是一个条件类型,用于剔除 T
中的 null
和 undefined
类型。
T extends null | undefined
:如果 T
是 null
或 undefined
,则结果为 never
。
: T
:如果 T
不是 null
或 undefined
,则结果为 T
。
10. Parameters<T>
获取函数类型 T
的参数类型组成的元组类型。
type Parameters<T extends (...args: any) => any>
:这是在定义一个泛型类型 Parameters
,它接受一个类型参数 T
,并且约束 T
必须是一个函数类型。
T extends (...args: any) => any
:确保 T
是一个函数类型,接受任意参数并返回任意类型的值。
T extends (...args: infer P) => any ? P : never
:这是一个条件类型,用于提取 T
的参数类型。
T extends (...args: infer P) => any
:如果 T
是一个函数类型,并且它的参数类型可以被推断为 P
,则结果为 P
。
? P
:如果 T
符合条件,返回参数类型 P
(即参数类型的元组)。
: never
:如果 T
不符合条件,返回 never
。
11. ConstructorParameters<T>
获取构造函数类型 T
的参数类型组成的元组类型。
type ConstructorParameters<T extends abstract new (...args: any) => any>
:这是在定义一个泛型类型 ConstructorParameters
,它接受一个类型参数 T
,并且约束 T
必须是一个构造函数类型。
T extends abstract new (...args: any) => any
:确保 T
是一个构造函数类型,接受任意参数并返回任意类型的实例。
T extends abstract new (...args: infer P) => any ? P : never
:这是一个条件类型,用于提取 T
的参数类型。
T extends abstract new (...args: infer P) => any
:如果 T
是一个构造函数类型,并且它的参数类型可以被推断为 P
,则结果为 P
。
? P
:如果 T
符合条件,返回参数类型 P
(即参数类型的元组)。
: never
:如果 T
不符合条件,返回 never
。
12. ReturnType<T>
获取函数类型 T
的返回值类型。
T extends (...args: any) => any
:这是一个泛型约束,确保 T
是一个函数类型。(...args: any) => any
表示一个接受任意参数并返回任意类型值的函数。
T extends (...args: any) => infer R ? R : any
:这是一个条件类型,用于提取函数类型 T
的返回值类型。
T extends (...args: any) => infer R
:如果 T
是一个函数类型,那么 infer R
会推断出该函数的返回值类型,并将其赋给类型变量 R
。
? R
:如果 T
是一个函数类型,则返回 R
,即函数的返回值类型。
: any
:如果 T
不是一个函数类型,则返回 any
。
13. InstanceType<T>
获取构造函数类型 T
的实例类型。
type InstanceType<T extends abstract new (...args: any) => any>
:这是在定义一个泛型类型 InstanceType
,它接受一个类型参数 T
,并且约束 T
必须是一个构造函数类型。
T extends abstract new (...args: any) => any
:确保 T
是一个构造函数类型,接受任意参数并返回任意类型的实例。
T extends abstract new (...args: any) => infer R ? R : any
:这是一个条件类型,用于提取构造函数 T
的实例类型。
T extends abstract new (...args: any) => infer R
:如果 T
是一个构造函数类型,并且它的返回类型可以被推断为 R
,则结果为 R
。
? R
:如果 T
符合条件,返回实例类型 R
。
: any
:如果 T
不符合条件,返回 any
。
14. ThisType<T>
用于指定上下文对象的类型。
interface ThisType<T>
:定义了一个泛型接口 ThisType
,它接受一个类型参数 T
。
{}
:这个接口没有任何具体的结构或成员。
ThisType<T>
是一个特殊的标记接口,用于告诉 TypeScript 在某些对象字面量的上下文中,this
应该被视为类型 T
。它通常与对象字面量的 contextual typing
结合使用,通过对象字面量中的 this
来实现更精确的类型检查。
15. Uppercase<T>, Lowercase<T>, Capitalize<T>, Uncapitalize<T>
16. Awaited<T>
获取 Promise 的解析值类型的工具类型
T extends null | undefined ? T
:处理 null
和 undefined
类型。如果 T
是 null
或 undefined
,则返回 T
。
T extends object & { then(onfulfilled: infer F, ...args: infer _): any; }
:检查 T
是否是一个对象,并且具有一个 then
方法。then
方法用于表示 thenable 对象,如 Promise
。
F extends ((value: infer V, ...args: infer _) => any)
:提取 then
方法的第一个参数类型 F
,并检查 F
是否是一个接受参数 V
的函数。
Awaited<V>
:递归地解包 V
,即如果 V
本身也是一个 Promise
或 thenable 对象,继续解包。
never
:如果 then
方法的第一个参数不是一个可调用函数,返回 never
。
T
:如果 T
既不是 null
或 undefined
,也不是一个 thenable 对象,则返回 T
。
关键字
infer
在 TypeScript 中,infer
关键字用于在条件类型中推断类型变量。它允许我们在条件类型中提取和使用某个类型的部分信息,是一个非常强大的特性。
infer
的用法
infer
关键字通常在条件类型中与 extends
关键字一起使用,以推断某个类型的一部分。如果类型符合某个模式,那么我们可以提取出这个模式的一部分作为类型变量。
示例
以下是一些使用 infer
关键字的示例:
示例 1:推断函数返回类型
我们可以创建一个工具类型 ReturnType
,用于提取函数的返回类型:
在这个例子中,MyReturnType
类型通过 infer
关键字提取出函数 exampleFunction
的返回类型 string
。
示例 2:推断数组元素类型
我们可以创建一个工具类型 ElementType
,用于提取数组的元素类型:
在这个例子中,ElementType
类型通过 infer
关键字提取出数组的元素类型。
深入理解
为了更好地理解 infer
,我们可以逐步拆解其用法:
- 定义条件类型:条件类型使用
extends
关键字来检查一个类型是否符合某个模式。
- 使用
infer
关键字:在条件类型中使用 infer
关键字来推断类型变量。
- 返回推断的类型:如果类型符合条件,则返回推断的类型;否则,返回其他类型(例如
never
)。
示例 3:推断 Promise 的解析类型
我们可以创建一个工具类型 Awaited
,用于提取 Promise
的解析类型:
在这个例子中,Awaited
类型通过 infer
关键字提取出 Promise
的解析类型。
实际应用
infer
关键字在实际开发中非常有用,特别是在构建复杂的类型系统时。例如,处理函数类型、数组类型或 Promise
类型时,可以使用 infer
来提取和操作类型信息。
例子:推断元组类型中的第一个元素类型
假设我们有一个元组类型,我们可以创建一个工具类型 FirstElement
,用于提取元组的第一个元素类型:
在这个例子中,FirstElement
类型通过 infer
关键字提取出元组的第一个元素类型。
intrinsic
在 TypeScript 中,intrinsic
是一个关键字,用于定义内置工具类型的行为。内置工具类型(例如 Uppercase
、Lowercase
、Capitalize
和 Uncapitalize
)是由 TypeScript 编译器直接支持的,并且它们的实现是内置在编译器中的。
虽然你在定义类型时可能会看到 intrinsic
关键字,但它并不是 TypeScript 用户需要直接使用或定义的东西。它是 TypeScript 编译器的一部分,用于实现复杂的类型变换。
typeof
typeof
是 TypeScript 中的一个关键字,用于获取变量或表达式的类型。它有两种主要用法:一种是用于类型查询,另一种是用于类型保护。
用法 1:类型查询
在 TypeScript 中,typeof
关键字可以用来获取变量的类型,并将其用作其他类型声明的一部分。这对于在类型系统中重用类型非常有用。
示例
在这个例子中,StringType
被赋值为 string
类型,而 NumberType
被赋值为 number
类型。typeof
用于获取变量 s
和 n
的类型。
用于函数返回类型
你还可以使用 typeof
来获取函数的返回类型:
在这个例子中,UserType
被赋值为 getUser
函数的返回类型 { name: string; age: number; }
。
用法 2:类型保护
typeof
关键字也可以用来在运行时检查变量的类型,从而实现类型保护。这在编写需要处理多种类型的函数时非常有用。
示例
在这个例子中,typeof id === "string"
用于检查 id
是否为字符串类型。如果是,则调用字符串的方法;否则,假定它是数字类型并调用数字的方法。
实际应用
类型查询的实际应用
类型查询在定义与现有变量或函数一致的类型时特别有用。例如,当你需要定义与函数返回类型一致的变量类型时:
类型保护的实际应用
类型保护在处理联合类型时非常有用。例如,处理多种输入类型:
type
在 TypeScript 中,type
关键字用于定义类型别名。类型别名为复杂的类型赋予一个新的名称,使代码更加清晰和易读。类型别名可以用于基本类型、对象类型、联合类型、交叉类型、函数类型、泛型等。
基本用法
定义基本类型的别名
定义对象类型的别名
定义联合类型的别名
定义交叉类型的别名
定义函数类型的别名
定义泛型类型的别名
对于交叉类型或联合类型的泛型参数
进阶用法
可索引类型
映射类型
条件类型
常用技巧