原文链接: https://dev.to/ibrahima92/advanced-typescript-types-cheat-sheet-with-examples-5414
经作者授权后翻译
文末送五本书
TypeScript
是一种类型化的语言,允许你指定变量的类型,函数参数,返回的值和对象属性。
这里是一个带有示例的高级 TypeScript
类型备忘单。
交叉类型是将多种类型组合为一种类型的方法。这意味着你可以将给定的类型A与类型B或更多类型合并,并获得具有所有属性的单个类型。
type LeftType = {
id: number
left: string
}
type RightType = {
id: number
right: string
}
type InterpType = LeftType & RightType
function showType(args: InterpType) {
console.log(args)
}
showType({
id: 1, left: "test", right: "test"
})
// Output: {id: 1, left: "test", right: "test"}
InterpType
组合了两种类型: LeftType
和 RightType
,并使用 &
符号构造交叉类型。
联合类型表示一个值可以是几种类型之一,例如某个函数希望传入 string
或者 number
类型的参数。
type UnionType = string | number
function showType(arg: UnionType) {
console.log(arg)
}
showType("test")
// Output: test
showType(7)
// Output: 7
函数 showType
的参数是一个联合类型,它接受 string
或 number
作为参数。
泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
function showType(args: T) {
console.log(args)
}
showType("test")
// Output: "test"
showType(1)
// Output: 1
要构造泛型,需要使用尖括号并将 T
作为参数传递。
在这里,我使用 T
(名称自定义),然后使用不同的类型两次调用 showType
函数。
interface GenericType {
id: number
name: T
}
function showType(args: GenericType) {
console.log(args)
}
showType({ id: 1, name: "test" })
// Output: {id: 1, name: "test"}
function showTypeTwo(args: GenericType) {
console.log(args)
}
showTypeTwo({ id: 1, name: 4 })
// Output: {id: 1, name: 4}
在这里,我们有另一个示例,该示例具有一个接口 GenericType
,该接口接收泛型 T
。由于它是可重用的,因此可以首先使用字符串,然后使用数字来调用它。
interface GenericType {
id: T
name: U
}
function showType(args: GenericType) {
console.log(args)
}
showType({ id: 1, name: "test" })
// Output: {id: 1, name: "test"}
function showTypeTwo(args: GenericType) {
console.log(args)
}
showTypeTwo({ id: "001", name: ["This", "is", "a", "Test"] })
// Output: {id: "001", name: Array["This", "is", "a", "Test"]}
泛型可以接收多个参数。在这里,我们传入两个参数:T
和 U
,然后将它们用作属性的类型。也就是说,我们现在可以使用该接口并提供不同的类型作为参数。
TypeScript
提供了方便的内置类型,可帮助轻松地操作类型。要使用它们,你需要将要转换的类型传递给 <>
Partial
Partial
允许你将 T
类型的所有属性设为可选。
interface PartialType {
id: number
firstName: string
lastName: string
}
function showType(args: Partial) {
console.log(args)
}
showType({ id: 1 })
// Output: {id: 1}
showType({ firstName: "John", lastName: "Doe" })
// Output: {firstName: "John", lastName: "Doe"}
如你所见,我们有一个 PartialType
接口,用作 showType()
函数接收的参数的类型。为了使属性成为可选属性,我们必须使用 Partial
关键字并将 PartialType
类型作为参数传递。也就是说,现在所有字段都变为可选。
Required
与 Partial
不同,Required
所有类型为 T
的属性成为必需。
interface RequiredType {
id: number
firstName?: string
lastName?: string
}
function showType(args: Required) {
console.log(args)
}
showType({ id: 1, firstName: "John", lastName: "Doe" })
// Output: { id: 1, firstName: "John", lastName: "Doe" }
showType({ id: 1 })
// Error: Type '{ id: number: }' is missing the following properties from type 'Required': firstName, lastName
即使我们之前设置的是可选属性,Required
也会使所有属性成为必需。如果省略属性,TypeScript
会抛出错误。
Readonly
Readonly
将 T
类型的所有属性变成只读属性。
interface ReadonlyType {
id: number
name: string
}
function showType(args: Readonly) {
args.id = 4
console.log(args)
}
showType({ id: 1, name: "Doe" })
// Error: Cannot assign to 'id' because it is a read-only property.
这里,我们使用 Readonly
来使 ReadonlyType
的属性变成只读属性。如果你尝试为这些字段赋值,则会引发错误。
除此之外,还可以在属性前面使用关键字 readonly
使其只读。
interface ReadonlyType {
readonly id: number
name: string
}
Pick
从 T
中取出 K
中指定的属性。
interface PickType {
id: number
firstName: string
lastName: string
}
function showType(args: Pick) {
console.log(args)
}
showType({ firstName: "John", lastName: "Doe" })
// Output: {firstName: "John"}
showType({ id: 3 })
// Error: Object literal may only specify known properties, and 'id' does not exist in type 'Pick'
Pick
需要两个参数 —— T
是要从中选择元素的类型,而 K
是要选择的属性。你也可以通过使用竖线( |
)分隔多个字段来选择多个字段。
Omit
Omit
与 Pick
相反,不是选择元素,而是从类型 T
中删除 K
属性。
interface PickType {
id: number
firstName: string
lastName: string
}
function showType(args: Omit) {
console.log(args)
}
showType({ id: 7 })
// Output: {id: 7}
showType({ firstName: "John" })
// Error: Object literal may only specify known properties, and 'firstName' does not exist in type 'Pick'
Extract
Extract
从 T
中提取所有可分配给 U
的类型。
interface FirstType {
id: number
firstName: string
lastName: string
}
interface SecondType {
id: number
address: string
city: string
}
type ExtractType = Extract
// Output: "id"
在这里,我们有两种共同的属性 id
。因此,通过使用 Extract
关键字,由于两个接口中都存在字段 id
,因此我们可以获取它。并且,如果有有多个共同字段,Extract
将提取所有共同的属性。
与 Extract
不同,Exclude
从 T
中排除所有可分配给 U
的类型。
interface FirstType {
id: number
firstName: string
lastName: string
}
interface SecondType {
id: number
address: string
city: string
}
type ExcludeType = Exclude
// Output; "firstName" | "lastName"
如上所示,属性 firstName
和 lastName
可分配给 ExcludeType
类型,因为它们在 SecondType
中不存在。
Record
Record
构造具有给定类型 T
的一组属性 K
的类型。在将一个类型的属性映射到另一个类型的属性时,Record
非常方便。
interface EmployeeType {
id: number
fullname: string
role: string
}
let employees: Record = {
0: { id: 1, fullname: "John Doe", role: "Designer" },
1: { id: 2, fullname: "Ibrahima Fall", role: "Developer" },
2: { id: 3, fullname: "Sara Duckson", role: "Developer" },
}
// 0: { id: 1, fullname: "John Doe", role: "Designer" },
// 1: { id: 2, fullname: "Ibrahima Fall", role: "Developer" },
// 2: { id: 3, fullname: "Sara Duckson", role: "Developer" }
Record
的工作方式相对简单。在这里,它期望数字作为类型,属性值的类型是 EmployeeType
,因此具有 id
,fullName
和 role
字段的对象。
NonNullable
NonNullable
从类型T中删除 null
和 undefined
。
type NonNullableType = string | number | null | undefined
function showType(args: NonNullable) {
console.log(args)
}
showType("test")
// Output: "test"
showType(1)
// Output: 1
showType(null)
// Error: Argument of type 'null' is not assignable to parameter of type 'string | number'.
showType(undefined)
// Error: Argument of type 'undefined' is not assignable to parameter of type 'string | number'.
在这里,我们将类型 NonNullableType
作为参数传递给 NonNullable
,NonNullable
将该类型中排除 null
和 undefined
来构造新类型。也就是说,如果传递可为空的值,TypeScript
将报错。
顺便说一句,如果将 --strictNullChecks
标志添加到 tsconfig
文件,TypeScript
将应用非空性规则。
映射类型允许你采用现有模型并将其每个属性转换为新类型。
type StringMap = {
[P in keyof T]: string
}
function showType(arg: StringMap<{ id: number; name: string }>) {
console.log(arg)
}
showType({ id: 1, name: "Test" })
// Error: Type 'number' is not assignable to type 'string'.
showType({ id: "testId", name: "This is a Test" })
// Output: {id: "testId", name: "This is a Test"}
StringMap<>
会将传入的任何类型转换为字符串。就是说,如果我们在函数 showType()
中使用它,则接收到的参数必须是字符串,否则,TypeScript
将报错。
类型保护使你可以使用运算符检查变量或对象的类型。
function showType(x: number | string) {
if (typeof x === "number") {
return `The result is ${x + x}`
}
throw new Error(`This operation can't be done on a ${typeof x}`)
}
showType("I'm not a number")
// Error: This operation can't be done on a string
showType(7)
// Output: The result is 14
我们有一个普通的 JavaScript
条件块,使用 typeof
来检查入参的类型。
instanceof
类型保护是通过构造函数来细化类型的一种方式。
class Foo {
bar() {
return "Hello World"
}
}
class Bar {
baz = "123"
}
function showType(arg: Foo | Bar) {
if (arg instanceof Foo) {
console.log(arg.bar())
return arg.bar()
}
throw new Error("The type is not supported")
}
showType(new Foo())
// Output: Hello World
showType(new Bar())
// Error: The type is not supported
interface FirstType {
x: number
}
interface SecondType {
y: string
}
function showType(arg: FirstType | SecondType) {
if ("x" in arg) {
console.log(`The property ${arg.x} exists`)
return `The property ${arg.x} exists`
}
throw new Error("This type is not expected")
}
showType({ x: 7 })
// Output: The property 7 exists
showType({ y: "ccc" })
// Error: This type is not expected
它测试两种类型,并根据该测试的结果选择其中一种。
type NonNullable = T extends null | undefined ? never : T
NonNullable
检查类型是否为 null
或者 undefined
,并根据检查结果进行处理。
谢谢阅读~
【通过阅读本书,你将学到】:
使用TypeScript和常用模式编写代码。
在TypeScript中使用流行的框架和库。
使用TypeScript来利用服务器和客户端的功能。
应用令人兴奋的新范式,如GraphQL和TensorFlow。
使用流行的、基于云的身份验证服务。
结合TypeScript和C#来创建ASP.NET Core应用程序。
【本书面向的读者】 本书的读者应该至少已经熟悉TypeScript的基础知识。如果你知道如何使用TypeScript编译器tsc来构建配置文件和编译代码,也知道TypeScript中的类型安全、函数和类等基础知识,那将大有裨益。即使你对TypeScript有比较深入的了解,本书中也会介绍一些你以前可能没有使用过的技术,你应该会对这些资料感兴趣。
本次活动将送出5本《TypeScript项目开发实战》
❝评论区留下你使用、学习TypeScript 的一些感想与感悟。或者为什么学习 TypeScript、以及对 TypeScript 的一些吐槽。一切你与 TypeScript 一切相关的都可以。
❞
留言点赞前三名
留言最走心两名
一切解释权归前端宇宙所有,获奖者必须添加小姐姐(老阿姨)微信:liuyanqdx