日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747


拿6個案例講解TypeScript 知識點(diǎn)「干貨」

 

作者:ssh前端

轉(zhuǎn)發(fā)鏈接:
https://mp.weixin.qq.com/s/ny_yya50PTJZX-IUERSueA

前言

相信這段時間來,對 TypeScript 感興趣的小伙伴們已經(jīng)把這個神器給系統(tǒng)的學(xué)習(xí)了一遍了吧。如果計(jì)劃開始學(xué)習(xí)但是還沒有開始,或者沒有找到資料的同學(xué),可以看下我在之前文章中 前端進(jìn)階指南[1] 找一下 TypeScript 部分的教程,自行學(xué)習(xí)。

本文從最近在 Github 上比較火的倉庫 typescript-exercises[2] 入手,它的中文介紹是 「富有挑戰(zhàn)性的 TypeScript 練習(xí)集」。里面包含了 15 個 TypeScript 的練習(xí)題,我會從其中挑選出幾個比較有價值的題目,一起來解答一下。

目標(biāo)

來看下這個倉庫的發(fā)起者所定下的目標(biāo),讓每個人都學(xué)會以下知識點(diǎn)的實(shí)戰(zhàn)運(yùn)用:

  1. Basic typing.
  2. Refining types.
  3. Union types.
  4. Merged types.
  5. Generics.
  6. Type declarations.
  7. Module augmentation.
  8. Advanced type mApping.

真的都是一些非常有難度且實(shí)用的知識點(diǎn),掌握了它們一定會讓我們在編寫 TypeScript 類型的時候如虎添翼。

挑戰(zhàn)

exercise-00

題目

import chalk from "chalk"

// 這里需要補(bǔ)全
const users: unknown[] = [
  {
    name: "Max Mustermann",
    age: 25,
    occupation: "Chimney sweep",
  },
  {
    name: "Kate Müller",
    age: 23,
    occupation: "Astronaut",
  },
]

// 這里需要補(bǔ)全
function logPerson(user: unknown) {
  console.log(` - ${chalk.green(user.name)}, ${user.age}`)
}

console.log(chalk.yellow("Users:"))
users.forEach(logPerson)

解答

第一題只是個熱身題,考察對接口類型定義的掌握,直接定義 User 接口即可實(shí)現(xiàn)。

interface User {
  name: string
  age: number
  occupation: string
}

const users: User[] = [
  {
    name: "Max Mustermann",
    age: 25,
    occupation: "Chimney sweep",
  },
  {
    name: "Kate Müller",
    age: 23,
    occupation: "Astronaut",
  },
]

function logPerson(user: User) {
  console.log(` - ${chalk.green(user.name)}, ${user.age}`)
}

console.log(chalk.yellow("Users:"))
users.forEach(logPerson)

或者利用類型推導(dǎo),users 數(shù)組會自動推斷出類型:

const users = [
  {
    name: "Max Mustermann",
    age: 25,
    occupation: "Chimney sweep",
  },
  {
    name: "Kate Müller",
    age: 23,
    occupation: "Astronaut",
  },
]

在 VSCode 中,鼠標(biāo)放到 users 變量上即可看到類型被自動推斷出來了:

{
  name: string
  age: number
  occupation: string
}
;[]

那么利用 typeof 關(guān)鍵字,配合索引查詢,我們也可以輕松取得這個類型。這里 number 的意思就是查找出 users 的所有數(shù)字下標(biāo)對應(yīng)的值的類型集合。

type User = typeof users[number]

這個倉庫提供了每道題的答題機(jī)制,執(zhí)行 npm run 0 對應(yīng)題號,看到結(jié)果即可證明編譯通過,答案正確。

拿6個案例講解TypeScript 知識點(diǎn)「干貨」

 

execsise-01

題目

最初,我們在數(shù)據(jù)庫中只有 User 類型,后來引入了 Admin 類型。把這兩個類型組合成 Person 類型以修復(fù)錯誤。

interface User {
  name: string
  age: number
  occupation: string
}

interface Admin {
  name: string
  age: number
  role: string
}

const persons: User[] /* <- Person[] */ = [
  {
    name: "Max Mustermann",
    age: 25,
    occupation: "Chimney sweep",
  },
  {
    name: "Jane Doe",
    age: 32,
    role: "Administrator",
  },
  {
    name: "Kate Müller",
    age: 23,
    occupation: "Astronaut",
  },
  {
    name: "Bruce Willis",
    age: 64,
    role: "World saver",
  },
]

function logPerson(user: User) {
  console.log(` - ${chalk.green(user.name)}, ${user.age}`)
}

persons.forEach(logPerson)

解答

本題考查聯(lián)合類型的使用:

// 定義聯(lián)合類型
type Person = User | Admin

const persons: Person[] /* <- Person[] */ = [
  {
    name: "Max Mustermann",
    age: 25,
    occupation: "Chimney sweep",
  },
  {
    name: "Jane Doe",
    age: 32,
    role: "Administrator",
  },
  {
    name: "Kate Müller",
    age: 23,
    occupation: "Astronaut",
  },
  {
    name: "Bruce Willis",
    age: 64,
    role: "World saver",
  },
]

function logPerson(user: Person) {
  console.log(` - ${chalk.green(user.name)}, ${user.age}`)
}

exercise-02

根據(jù)上題中定義出的 Person 類型,現(xiàn)在需要一個方法打印出它的實(shí)例:

題目

function logPerson(person: Person) {
  let additionalInformation: string
  if (person.role) {
    // ? 報(bào)錯 Person 類型中不一定有 role 屬性
    additionalInformation = person.role
  } else {
    // ? 報(bào)錯 Person 類型中不一定有 occupation 屬性
    additionalInformation = person.occupation
  }
  console.log(
    ` - ${chalk.green(person.name)}, ${person.age}, ${additionalInformation}`,
  )
}

解答

本題考查 TypeScript 中的「類型保護(hù)」,TypeScript 的程序流分析使得某些判斷代碼包裹之下的代碼中,類型可以被進(jìn)一步收縮。

in 操作符:

function logPerson(person: Person) {
  let additionalInformation: string
  if ("role" in person) {
    additionalInformation = person.role
  } else {
    additionalInformation = person.occupation
  }
  console.log(
    ` - ${chalk.green(person.name)}, ${person.age}, ${additionalInformation}`,
  )
}

函數(shù)返回值中的 is 推斷:

function isAdmin(user: Person): user is Admin {
  return user.hasOwnProperty("role")
}

function logPerson(person: Person) {
  let additionalInformation: string
  if (isAdmin(person)) {
    additionalInformation = person.role
  } else {
    additionalInformation = person.occupation
  }
  console.log(
    ` - ${chalk.green(person.name)}, ${person.age}, ${additionalInformation}`,
  )
}

exercise-04

題目

本題定義了一個 filterUsers 方法,用來通過 person 中的某些字段來篩選出用戶的子集。

function filterUsers(persons: Person[], criteria: User): User[] {
  return persons.filter(isUser).filter((user) => {
    let criteriaKeys = Object.keys(criteria) as (keyof User)[]
    return criteriaKeys.every((fieldName) => {
      return user[fieldName] === criteria[fieldName]
    })
  })
}

console.log(chalk.yellow("Users of age 23:"))

filterUsers(
  persons,
  // ? 報(bào)錯,criteria 定義的是精確的 User 類型,少字段了。
  {
    age: 23,
  },
).forEach(logPerson)

可以看出,由于 filterUsers 的第二個篩選參數(shù)的類型被精確的定義為User,所以只傳入它的一部分字段 age 就會報(bào)錯。

解答

本題考查 [mapped-types](
https://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types "mapped-types") 映射類型,

type Criteria = {
  [K in keyof User]?: User[K]
}

function filterUsers(persons: Person[], criteria: Criteria): User[] {
  return persons.filter(isUser).filter((user) => {
    let criteriaKeys = Object.keys(criteria) as (keyof User)[]
    return criteriaKeys.every((fieldName) => {
      return user[fieldName] === criteria[fieldName]
    })
  })
}

Criteria 利用了映射類型,把 User 的 key 值遍歷了一遍,并且加上了 ? 標(biāo)志代表字段都是可選的,即可完成任務(wù)。

也可以利用內(nèi)置類型 Partial,這個類型用于把另一個類型的字段全部轉(zhuǎn)為可選。

function filterUsers(persons: Person[], criteria: Partial<User>): User[] {}

exercise-05

題目

function filterPersons(  persons: Person[],
  personType: string,
  criteria: unknown,): unknown[] {}

let usersOfAge23: User[] = filterPersons(persons, "user", { age: 23 })
let adminsOfAge23: Admin[] = filterPersons(persons, "admin", { age: 23 })

解答

本題返回值類型即可以是 User,也可以是Admin,并且很明顯這個結(jié)果是由第二個參數(shù)是 'user' 還是 'admin' 所決定。

利用函數(shù)重載的功能,可以輕松實(shí)現(xiàn),針對每種不同的 personType 參數(shù)類型,我們給出不同的返回值類型:

function filterPersons(  persons: Person[],
  personType: "admin",
  criteria: Partial<Person>,): Admin[]
function filterPersons(  persons: Person[],
  personType: "user",
  criteria: Partial<Person>,): User[]
function filterPersons(  persons: Person[],
  personType: string,
  criteria: Partial<Person>,) {}

let usersOfAge23: User[] = filterPersons(persons, "user", { age: 23 })
let adminsOfAge23: Admin[] = filterPersons(persons, "admin", { age: 23 })

exercise-06

題目

function swap(v1, v2) {
  return [v2, v1]
}

function test1() {
  console.log(chalk.yellow("test1:"))
  const [secondUser, firstAdmin] = swap(admins[0], users[1])
  logUser(secondUser)
  logAdmin(firstAdmin)
}

function test2() {
  console.log(chalk.yellow("test2:"))
  const [secondAdmin, firstUser] = swap(users[0], admins[1])
  logAdmin(secondAdmin)
  logUser(firstUser)
}

解答

本題的關(guān)鍵點(diǎn)是 swap 這個方法,它即可以接受Admin類型為參數(shù),也可以接受User 類型為參數(shù),并且還需要根據(jù)傳入?yún)?shù)的順序把它們倒過來放在數(shù)組中放回。

也就是說傳入的是 v1: User, v2: Admin,需要返回 [Admin, User] 類型。

這題就比較有難度了,首先需要用到泛型[3] 來推斷出參數(shù)類型,并且和結(jié)果關(guān)聯(lián)起來:

function swap<T, K>(v1: T, v2: K) {
  return [v2, v1]
}

此時結(jié)果沒有按照我們預(yù)期的被推斷成 [K, T],而是被推斷成了 (K | T)[],這是不符合要求的。

這是因?yàn)?TypeScript 默認(rèn)我們數(shù)組中的元素是可變的,所以它會「悲觀的」推斷我們可能會改變元素的順序。鼠標(biāo)放到運(yùn)行函數(shù)時的swap上,我們可以看出類型被推斷為了:

function swap<Admin, User>(v1: Admin, v2: User): (Admin | User)[]

要改變這一行為,我們加上 as const 來聲明它為常量,嚴(yán)格保證順序。

function swap<T, K>(v1: T, v2: K) {
  return [v2, v1] as const
}

此時再看看 swap的推斷:

function swap<Admin, User>(v1: Admin, v2: User): readonly [User, Admin]

類型被自動加上了 readonly,并且也嚴(yán)格的維持了順序,太棒啦。

總結(jié)

先用其中的幾道題練練手,到第六題的時候,已經(jīng)涉及到了一些進(jìn)階的用法,非常有挑戰(zhàn)性。不知道小伙伴們對于這樣的做題形式是否感興趣,還剩下不少有挑戰(zhàn)性的題目,如果反饋不錯的話,我會繼續(xù)更新這個系列。

分享到:
標(biāo)簽:TypeScript
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定