高级TypeScript类型备忘单(带示例)

https://dev.to/ibrahima92/advanced-typescript-types-cheat-sheet-with-examples-5414 转载

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({ id: 1, left: "test", right: "test" })
// Output: {id: 1, left: "test", right: "test"}

如您所见,IntersectionType结合了两种类型——LeftType和RightType,并使用&符号来构造交集类型。

2 联合类型 允许在给定变量中拥有不同的类型注释。

type UnionType = string | number

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

showType("test")
// Output: test

showType(7)

函数showType是一个联合类型,接受字符串和数字作为参数

3 泛型类型 是重用给定类型的一部分的一种方式。它有助于捕获作为参数传入的类型T。

function showType<T>(args: T) {
  console.log(args)
}

showType("test")
// Output: "test"

showType(1)
// Output: 1

要构造泛型类型,需要使用方括号并将T作为参数传递。

这里,我使用T(名称由您决定),然后使用不同的类型注释调用函数showType两次,因为它是泛型的——它可以重用。

interface GenericType<T> {
  id: number
  name: T
}

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

showType({ id: 1, name: "test" })
// Output: {id: 1, name: "test"}

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

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

 这里,我们有另一个例子,它有一个接口GenericType,它接收一个泛型类型t。由于它是可重用的,我们可以先用一个字符串,然后用一个数字来调用它

interface GenericType<T, U> {
  id: T
  name: U
}

function showType(args: GenericType<number, string>) {
  console.log(args)
}

showType({ id: 1, name: "test" })
// Output: {id: 1, name: "test"}

function showTypeTwo(args: GenericType<string, string[]>) {
  console.log(args)
}

showTypeTwo({ id: "001", name: ["This", "is", "a", "Test"] })
// Output: {id: "001", name: Array["This", "is", "a", "Test"]}

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

4实用程序类

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

 

部分< T >

Partial允许您使类型T的所有属性都是可选的。它会添加a ?在每个字段旁边标记。

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

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

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

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

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

 

5 要求需要< T >

与Partial不同,Required实用程序生成类型T的所有属性。


  id: number
  firstName?: string
  lastName?: string
}

function showType(args: Required<RequiredType>) {
  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<RequiredType>': firstName, lastName

Required实用程序将使所有属性都成为必需的,即使我们在使用实用程序之前先将它们设置为可选的。如果省略了某个属性,TypeScript会抛出一个错误。

6 只读的< T >

这个实用程序类型将转换类型T的所有属性,以使它们不能用新值重新分配。

interface ReadonlyType {
  id: number
  name: string
}

function showType(args: Readonly<ReadonlyType>) {
  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
}

7选择< T, K >

它允许您通过选择现有模型T的一些属性K来创建新类型。

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

function showType(args: Pick<PickType, "firstName" | "lastName">) {
  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<PickType, "firstName" | "lastName">'

Pick与我们已经看到的前面的实用程序有一点不同。它需要两个参数——T是您想要从中选择元素的类型,K是您想要选择的属性。您还可以通过使用管道(|)符号将它们分开来选择多个字段。

8省略< T, K >

省略实用程序与Pick类型相反。它将从类型T中删除K个属性,而不是选择元素。

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

function showType(args: Omit<PickType, "firstName" | "lastName">) {
  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<PickType, "id">'

这个实用程序类似于Pick的工作方式。它期望类型和属性从该类型中省略。

 

8提取< T U >

Extract允许您通过选择两种不同类型的属性来构造类型。该实用程序将提取从T所有的属性,是分配给U。

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

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

type ExtractType = Extract<keyof FirstType, keyof SecondType>
// Output: "id"

在这里,我们有两种类型的共同属性id。因此,通过使用Extract关键字,我们得到字段id,因为它在两个接口中都存在。如果您有多个共享字段,该实用程序将提取所有类似的属性。

9 排除

与Extract不同,Exclude实用程序将通过排除已经存在于两种不同类型中的属性来构造类型。它排除了所有可分配给U的字段。

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

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

type ExcludeType = Exclude<keyof FirstType, keyof SecondType>

// Output; "firstName" | "lastName"

正如您在这里看到的,属性firstName和lastName可分配给SecondType类型,因为它们不存在。通过使用Extract关键字,我们将按预期获得这些字段。

10 记录< K, T >

这个实用程序帮助您构造一个具有一组给定类型t的属性K的类型。当需要将一个类型的属性映射到另一个类型时,Record非常方便。

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

let employees: Record<number, EmployeeType> = {
  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的工作方式相对简单。这里,它期望一个数字作为类型,这就是为什么我们将0、1和2作为employees变量的键。如果尝试使用字符串作为属性,则会抛出错误。接下来,属性集由EmployeeType给出,因此对象包含字段id、fullName和role。

11 NonNullable < T >

它允许您从类型T中删除null和undefined。

type NonNullableType = string | number | null | undefined

function showType(args: NonNullable<NonNullableType>) {
  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实用程序,该实用程序通过从该类型中排除null和undefined来构造一个新类型。也就是说,如果你传递一个可为空的值,TypeScript会抛出一个错误。

顺便说一下,如果你在tsconfig文件中添加——strictNullChecks标志,TypeScript会应用非空性规则。

12 映射类型

映射类型允许您获取一个现有的模型,并将其每个属性转换为一个新类型。注意,前面介绍的一些实用程序类型也是映射类型。

type StringMap<T> = {
  [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将抛出一个错误。

13 类型警卫 类型保护允许您使用操作符检查变量或对象的类型。它是一个条件块,使用typeof、instanceof或in返回类型

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

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

与前面的示例一样,这个示例也是一个类型保护,它检查接收到的参数是否是Foo类的一部分,然后对其进行处理。

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({ x: 7 })
// Output: The property 7 exists

showType({ y: "ccc" })
// Error: This type is not expected

in操作符允许您检查作为参数接收的对象上是否存在属性x。

 

14 有条件的类型  它测试两种类型,并根据测试结果选择其中一种。

type NonNullable<T> = T extends null | undefined ? never : T

这个非空实用程序类型的例子检查类型是否为空,并根据它来处理。正如您所注意到的,它使用JavaScript三元操作符。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值