高階TypeScript型別備忘單(帶示例)

qq_34703156發表於2020-12-28

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三元操作符。

 

 

相關文章