TypeScript高级类型备忘录(附示例)

前端宇宙

共 8702字,需浏览 18分钟

 ·

2020-09-12 01:49

原文链接: https://dev.to/ibrahima92/advanced-typescript-types-cheat-sheet-with-examples-5414

经作者授权后翻译

文末送五本书

TypeScript 是一种类型化的语言,允许你指定变量的类型,函数参数,返回的值和对象属性。

这里是一个带有示例的高级 TypeScript 类型备忘单。

1. 交叉类型

交叉类型是将多种类型组合为一种类型的方法。这意味着你可以将给定的类型A与类型B或更多类型合并,并获得具有所有属性的单个类型。

type LeftType = {
    id: number
    left: string
}

type RightType = {
    id: number
    right: string
}

type IntersectionType = LeftType & RightType

function showType(args: IntersectionType{
    console.log(args)
}

showType({
    id1left"test"right"test"
})
// Output: {id: 1, left: "test", right: "test"}

IntersectionType 组合了两种类型: LeftTypeRightType ,并使用 符号构造交叉类型。

2. 联合类型

联合类型表示一个值可以是几种类型之一,例如某个函数希望传入 string 或者 number 类型的参数。

type UnionType = string | number

function showType(arg: UnionType{
    console.log(arg)
}

showType("test")
// Output: test

showType(7)
// Output: 7

函数 showType 的参数是一个联合类型,它接受 stringnumber 作为参数。

3.泛型

泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。

function showType<T>(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({ id1name"test" })
// Output: {id: 1, name: "test"}

function showTypeTwo(args: GenericType{
    console.log(args)
}

showTypeTwo({ id1name4 })
// Output: {id: 1, name: 4}

在这里,我们有另一个示例,该示例具有一个接口 GenericType,该接口接收泛型 T 。由于它是可重用的,因此可以首先使用字符串,然后使用数字来调用它。

interface GenericType {
    id: T
    name: U
}

function showType(args: GenericType{
    console.log(args)
}

showType({ id1name"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"]}

泛型可以接收多个参数。在这里,我们传入两个参数:TU,然后将它们用作属性的类型。也就是说,我们现在可以使用该接口并提供不同的类型作为参数。

内置类型

TypeScript 提供了方便的内置类型,可帮助轻松地操作类型。要使用它们,你需要将要转换的类型传递给 <>

Partial

  • Partial

Partial 允许你将 T 类型的所有属性设为可选。

interface PartialType {
    id: number
    firstName: string
    lastName: string
}

function showType(args: Partial{
    console.log(args)
}

showType({ id1 })
// Output: {id: 1}

showType({ firstName"John"lastName"Doe" })
// Output: {firstName: "John", lastName: "Doe"}

如你所见,我们有一个 PartialType 接口,用作 showType() 函数接收的参数的类型。为了使属性成为可选属性,我们必须使用 Partial 关键字并将 PartialType 类型作为参数传递。也就是说,现在所有字段都变为可选。

Required

  • Required

Partial 不同,Required 所有类型为 T 的属性成为必需。

interface RequiredType {
    id: number
    firstName?: string
    lastName?: string
}

function showType(args: Required{
    console.log(args)
}

showType({ id1firstName"John"lastName"Doe" })
// Output: { id: 1, firstName: "John", lastName: "Doe" }

showType({ id1 })
// Error: Type '{ id: number: }' is missing the following properties from type 'Required': firstName, lastName

即使我们之前设置的是可选属性,Required 也会使所有属性成为必需。如果省略属性,TypeScript 会抛出错误。

Readonly

  • Readonly

ReadonlyT 类型的所有属性变成只读属性。

interface ReadonlyType {
    id: number
    name: string
}

function showType(args: Readonly{
    args.id = 4
    console.log(args)
}

showType({ id1name"Doe" })
// Error: Cannot assign to 'id' because it is a read-only property.

这里,我们使用 Readonly 来使 ReadonlyType 的属性变成只读属性。如果你尝试为这些字段赋值,则会引发错误。

除此之外,还可以在属性前面使用关键字 readonly 使其只读。

interface ReadonlyType {
    readonly id: number
    name: string
}

Pick

  • Pick

T 中取出 K 中指定的属性。

interface PickType {
    id: number
    firstName: string
    lastName: string
}

function showType(args: Pick"firstName" | "lastName">) {
    console.log(args)
}

showType({ firstName"John"lastName"Doe" })
// Output: {firstName: "John"}

showType({ id3 })
// Error: Object literal may only specify known properties, and 'id' does not exist in type 'Pick'

Pick 需要两个参数 —— T 是要从中选择元素的类型,而 K 是要选择的属性。你也可以通过使用竖线( | )分隔多个字段来选择多个字段。

Omit

  • Omit

OmitPick 相反,不是选择元素,而是从类型 T 中删除 K 属性。

interface PickType {
    id: number
    firstName: string
    lastName: string
}

function showType(args: Omit"firstName" | "lastName">) {
    console.log(args)
}

showType({ id7 })
// Output: {id: 7}

showType({ firstName"John" })
// Error: Object literal may only specify known properties, and 'firstName' does not exist in type 'Pick'

Extract

  • Extract

ExtractT 中提取所有可分配给 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 将提取所有共同的属性。

Exclude

Extract 不同,ExcludeT 中排除所有可分配给 U 的类型。

interface FirstType {
    id: number
    firstName: string
    lastName: string
}

interface SecondType {
    id: number
    address: string
    city: string
}

type ExcludeType = Exclude

// Output; "firstName" | "lastName"

如上所示,属性 firstNamelastName 可分配给 ExcludeType 类型,因为它们在 SecondType 中不存在。

Record

  • Record

Record 构造具有给定类型 T 的一组属性 K 的类型。在将一个类型的属性映射到另一个类型的属性时,Record 非常方便。

interface EmployeeType {
    id: number
    fullname: string
    role: string
}

let employees: Record = {
    0: { id1fullname"John Doe"role"Designer" },
    1: { id2fullname"Ibrahima Fall"role"Developer" },
    2: { id3fullname"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 ,因此具有 idfullNamerole 字段的对象。

NonNullable

  • NonNullable

NonNullable 从类型T中删除 nullundefined

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 作为参数传递给 NonNullableNonNullable 将该类型中排除 nullundefined 来构造新类型。也就是说,如果传递可为空的值,TypeScript 将报错。

顺便说一句,如果将 --strictNullChecks 标志添加到 tsconfig 文件,TypeScript 将应用非空性规则。

Mapped types

映射类型允许你采用现有模型并将其每个属性转换为新类型。

type StringMap = {
    [P in keyof T]: string
}

function showType(arg: StringMap<{ id: number; name: string }>{
    console.log(arg)
}

showType({ id1name"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 将报错。

类型保护

类型保护使你可以使用运算符检查变量或对象的类型。

typeof
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

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
in
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({ x7 })
// 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,并根据检查结果进行处理。

谢谢阅读~

送五本书


【全书共10章】:第1章介绍你之前可能没有接触过的TypeScript功能, 第2章将编写第一个实用的项目——一个简单的markdown编辑器, 第3章将使用流行的React库构建一个联系人管理器, 第4章介绍MEAN栈, 第5章介绍如何使用GraphQL和Apollo创建Angular待办事项应用程序, 第6章介绍如何使用Socket.IO构建一个聊天室应用程序, 第7章介绍如何使用必应地图和Firebase创建基于云的Angular地图应用程序, 第8章介绍如何使用一个等效的基于React的栈, 第9章介绍如何使用TensorFlow.js在Web浏览器中托管机器学习, 第10章介绍如何使用ASP.NET Core和免费的Discogs音乐API来编写一个音乐库应用程序。
【通过阅读本书,你将学到】:
  • 使用TypeScript和常用模式编写代码。
  • 在TypeScript中使用流行的框架和库。
  • 使用TypeScript来利用服务器和客户端的功能。
  • 应用令人兴奋的新范式,如GraphQL和TensorFlow。
  • 使用流行的、基于云的身份验证服务。
  • 结合TypeScript和C#来创建ASP.NET Core应用程序。
【本书面向的读者】 本书的读者应该至少已经熟悉TypeScript的基础知识。如果你知道如何使用TypeScript编译器tsc来构建配置文件和编译代码,也知道TypeScript中的类型安全、函数和类等基础知识,那将大有裨益。即使你对TypeScript有比较深入的了解,本书中也会介绍一些你以前可能没有使用过的技术,你应该会对这些资料感兴趣。
本次活动将送出5《TypeScript项目开发实战》

评论区留下你使用、学习TypeScript 的一些感想与感悟。或者为什么学习 TypeScript、以及对 TypeScript 的一些吐槽。一切你与 TypeScript 一切相关的都可以。

  • 留言点赞前三名
  • 留言最走心两名 

一切解释权归前端宇宙所有,获奖者必须添加小姐姐(老阿姨)微信:liuyanqdx

浏览 14
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报