<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          TypeScript 練習(xí)題

          共 12824字,需瀏覽 26分鐘

           ·

          2020-09-29 23:20


          點(diǎn)擊藍(lán)色“腦洞前端”關(guān)注我喲

          加個“星標(biāo)”,帶你揭開大前端的神秘面紗!

          ?

          這是腦洞前端第「105」篇原創(chuàng)文章

          TypeScript 的學(xué)習(xí)資料非常多,其中也不乏很多優(yōu)秀的文章和教程。但是目前為止沒有一個我特別滿意的。原因有:

          • 它們大多數(shù)沒有一個清晰的主線,而是按照 API 組織章節(jié)的,內(nèi)容在「邏輯上」比較零散。
          • 大多是“講是什么,怎么用“,而不是”講為什么,講原理“。
          • 大多數(shù)內(nèi)容比較枯燥,趣味性比較低。都是干巴巴的文字,沒有圖片,缺乏能夠引起強(qiáng)烈共鳴的例子。

          因此我的想法是做一套不同市面上大多數(shù)的 TypeScript 學(xué)習(xí)教程。以人類認(rèn)知的角度思考問題,學(xué)習(xí) TypeScript,通過通俗易懂的例子和圖片來幫助大家建立 TypeScript 世界觀。

          系列安排:

          ?

          目錄將來可能會有所調(diào)整。

          ?

          注意,我的系列文章基本不會講 API,因此需要你有一定的 TypeScript 使用基礎(chǔ),推薦兩個學(xué)習(xí)資料。

          • 深入理解 TypeScript[1]
          • TypeScript 官方文檔[2]

          結(jié)合這兩個資料和我的系列教程,掌握 TypeScript 指日可待。

          接下來,我們通過幾個方面來從宏觀的角度來看一下 TypeScript。

          前言

          本文涉及的題目一共十六道,全部都可以在 typescript-exercises[3] 上在線提交。

          可以和標(biāo)準(zhǔn)答案進(jìn)行對比。

          并且由于使用了瀏覽器緩存, 因此無需登錄的情況下也可以保證關(guān)掉頁面,你的答題進(jìn)度也會保留。

          ?

          想重置進(jìn)度,清空緩存,無痕模式或者換瀏覽器都可以。

          ?

          題目中涉及到的知識點(diǎn)我基本也都在之前的文章中提到了,如果你沒有看過,強(qiáng)烈建議先完成前面的教程,然后將上面的題目自己做一遍之后再看本文。

          為了不讓文章太過于冗長, 本篇文章分兩次發(fā)布, 一次 8 道題,一共十六道。每道題都有思路,前置知識以及代碼。

          題目一

          題目描述

          Intro:

          ????We?are?starting?a?small?community?of?users.?For?performance
          ????reasons?we?have?decided?to?store?all?users?right?in?the?code.
          ????This?way?we?can?provide?our?developers?with?more
          ????user-interaction?opportunities.?With?user-related?data,?at?least.
          ????All?the?GDPR-related?issues?we?will?solved?some?other?day.
          ????This?would?be?the?base?for?our?future?experiments?during
          ????these?exercises.

          Exercise:

          ????Given?the?data,?define?the?interface?"User"?and?use?it?accordingly.

          題目的大概意思是讓你定義一個類型 User, 使得代碼可以正常運(yùn)行。

          題目內(nèi)置代碼

          export?type?User?=?unknown;

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

          export?function?logPerson(user:?unknown)?{
          ??console.log(`?-?${user.name},?${user.age}`);
          }

          console.log("Users:");
          users.forEach(logPerson);

          前置知識

          • interface 或 type 聲明自定義類型

          思路

          這道題比較簡單, 我們只有定義一個 User 類即可。從 users 數(shù)組中不難看出, User 中有三個屬性 name ,age 和 occupation,類型分別為 string, number 和 string。因此直接使用 type 或者 interface 定義自定義類型即可。

          代碼

          核心代碼:

          export?type?User?=?{
          ??name:?string;
          ??age:?number;
          ??occupation:?string;
          };

          題目二

          題目描述

          Intro:

          ????All?2?users?liked?the?idea?of?the?community.?We?should?go
          ????forward?and?introduce?some?order.?We?are?in?Germany?after?all.
          ????Let's?add?a?couple?of?admins.

          ????Initially?we?only?had?users?in?the?in-memory?database.?After
          ????introducing?Admins,?we?need?to?fix?the?types?so?that
          ????everything?works?well?together.

          Exercise:

          ????Type?"Person"?is?missing,?please?define?it?and?use
          ????it?in?persons?array?and?logPerson?function?in?order?to?fix
          ????all?the?TS?errors.

          題目大意是補(bǔ)充 Person 類, 使得代碼不報錯。

          題目內(nèi)置代碼

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

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

          export?type?Person?=?unknown;

          export?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",
          ??},
          ];

          export?function?logPerson(user:?User)?{
          ??console.log(`?-?${user.name},?${user.age}`);
          }

          persons.forEach(logPerson);

          前置知識

          • 聯(lián)合類型

          思路

          我們直接從報錯入手。

          不難發(fā)現(xiàn) persons 數(shù)組既有 User 又有 Admin。因此 person 的函數(shù)簽名應(yīng)該是兩者的聯(lián)合類型。而題目又讓我們補(bǔ)充 Person,于是代碼將 Person 定義為 Admin 和 User 的聯(lián)合類型就不難想到。

          代碼

          核心代碼:

          export?type?Person?=?User?|?Admin;

          這個時候, persons 數(shù)組使用的過程只能用 User 和 Admin 的共有屬性, 也就是 name 和 age,這點(diǎn)后面的題目也會提到。因此如果你使用了 role 或者 occupation 就會報錯。怎么解決呢?我們繼續(xù)看下一題。

          第三題

          題目描述

          Intro:

          ????Since?we?already?have?some?of?the?additional
          ????information?about?our?users,?it's?a?good?idea
          ????to?output?it?in?a?nice?way.

          Exercise:

          ????Fix?type?errors?in?logPerson?function.

          ????logPerson?function?should?accept?both?User?and?Admin
          ????and?should?output?relevant?information?according?to
          ????the?input:?occupation?for?User?and?role?for?Admin.

          題目內(nèi)置代碼

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

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

          export?type?Person?=?User?|?Admin;

          export?const?persons:?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",
          ??},
          ];

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

          persons.forEach(logPerson);

          前置知識

          • 類型斷言
          • 類型收斂
          • in 操作符

          思路

          關(guān)于類型收斂, 我在 TypeScript 類型系統(tǒng) 做了很詳情的討論。

          上面代碼報錯的原因前面已經(jīng)講過了, 那么如何解決呢?由于 person 可能是 User ,也可能是 Admin 類型,而 TypeScript 沒有足夠的信息確定具體是哪一種。因此你使用 User 或者 Admin 特有的屬性就會報錯了。

          因此解決方案的基本思想就是告訴 TypeScript 「person 當(dāng)前是 Admin 還是 User 類型」。有多種方式可以解決這個問題。

          1. 將 person 斷言為準(zhǔn)確的類型。就是告訴 TypeScript ”交給我吧, person 就是 xxx 類型,有錯就我的鍋“。

          代碼:

          if?((person).role)?{
          ??additionalInformation?=?(person).role;
          }?else?{
          ??additionalInformation?=?(person).occupation;
          }
          1. 另外一種方式是使用類型收縮,比如 is , in, typeof , instanceof 等。使得 Typescript 能夠 Get 到當(dāng)前的類型。”哦, person 上有 role 屬性啊,那它就是 Admin 類型,有問題我 Typescript 的鍋“

          這里我們使用 in 操作符,寫起來也很簡單。

          ?

          推薦哪種不用我多說了吧 ?

          ?

          代碼

          if?("role"?in?person)?{
          ??//?person?會被自動推導(dǎo)為?Admin
          ??additionalInformation?=?person.role;
          }?else?{
          ??//?Person?會被自動推導(dǎo)為?User
          ??additionalInformation?=?person.occupation;
          }

          第四題

          題目描述

          Intro:

          ????As?we?introduced?"type"?to?both?User?and?Admin
          ????it's?now?easier?to?distinguish?between?them.
          ????Once?object?type?checking?logic?was?extracted
          ????into?separate?functions?isUser?and?isAdmin?-
          ????logPerson?function?got?new?type?errors.

          Exercise:

          ????Figure?out?how?to?help?TypeScript?understand?types?in
          ????this?situation?and?apply?necessary?fixes.

          大概意思還是讓你改代碼, 使得 Typescript 能理解(不報錯)。

          題目內(nèi)置代碼

          interface?User?{
          ??type:?"user";
          ??name:?string;
          ??age:?number;
          ??occupation:?string;
          }

          interface?Admin?{
          ??type:?"admin";
          ??name:?string;
          ??age:?number;
          ??role:?string;
          }

          export?type?Person?=?User?|?Admin;

          export?const?persons:?Person[]?=?[
          ??{
          ????type:?"user",
          ????name:?"Max?Mustermann",
          ????age:?25,
          ????occupation:?"Chimney?sweep",
          ??},
          ??{?type:?"admin",?name:?"Jane?Doe",?age:?32,?role:?"Administrator"?},
          ??{?type:?"user",?name:?"Kate?Müller",?age:?23,?occupation:?"Astronaut"?},
          ??{?type:?"admin",?name:?"Bruce?Willis",?age:?64,?role:?"World?saver"?},
          ];

          export?function?isAdmin(person:?Person)?{
          ??return?person.type?===?"admin";
          }

          export?function?isUser(person:?Person)?{
          ??return?person.type?===?"user";
          }

          export?function?logPerson(person:?Person)?{
          ??let?additionalInformation:?string?=?"";
          ??if?(isAdmin(person))?{
          ????additionalInformation?=?person.role;
          ??}
          ??if?(isUser(person))?{
          ????additionalInformation?=?person.occupation;
          ??}
          ??console.log(`?-?${person.name},?${person.age},?${additionalInformation}`);
          }

          console.log("Admins:");
          persons.filter(isAdmin).forEach(logPerson);

          console.log();

          console.log("Users:");
          persons.filter(isUser).forEach(logPerson);

          前置知識

          • 類型收斂
          • is 操作符

          思路

          我們?nèi)匀粡膱箦e入手。

          實(shí)際上還是 person 的類型問題, 沒有被收縮到正確的類型。看題目的代碼,期望效果應(yīng)該是如果進(jìn)入 isAdmin 內(nèi)部,那么 person 就是 Admin 類型,同理進(jìn)入 isUser 內(nèi)部,那么 person 就是 User 類型。

          繼續(xù)看下 isAdmin 和 isUser 的實(shí)現(xiàn):

          export?function?isAdmin(person:?Person)?{
          ??return?person.type?===?"admin";
          }

          export?function?isUser(person:?Person)?{
          ??return?person.type?===?"user";
          }

          這里我們期望的效果是如果 isAdmin 函數(shù)返回 true ,那么 person 就應(yīng)該被收斂為 Admin,isUser 同理。

          這里就需要用到 is 操作符。

          ?

          上文提到了類型收斂常見的操作符是 is , in, typeof , instanceof

          ?

          代碼

          export?function?isAdmin(person:?Person):?person?is?Admin?{
          ??return?person.type?===?"admin";
          }

          export?function?isUser(person:?Person):?person?is?User?{
          ??return?person.type?===?"user";
          }

          這樣當(dāng) isAdmin 返回 true, 那么 person 變量就會被推導(dǎo)成 Admin 類型,而不是聯(lián)合類型, 也就是類型發(fā)生了收縮。

          不難看出,這樣的類型斷言會直接影響到調(diào)用 isAdmin 或 isUser 的「函數(shù)的入?yún)⒌念愋汀?/strong>。

          第五題

          題目描述

          Intro:

          ????Time?to?filter?the?data!?In?order?to?be?flexible
          ????we?filter?users?using?a?number?of?criteria?and
          ????return?only?those?matching?all?of?the?criteria.
          ????We?don't?need?Admins?yet,?we?only?filter?Users.

          Exercise:

          ????Without?duplicating?type?structures,?modify
          ????filterUsers?function?definition?so?that?we?can
          ????pass?only?those?criteria?which?are?needed,
          ????and?not?the?whole?User?information?as?it?is
          ????required?now?according?to?typing.

          Higher?difficulty?bonus?exercise:

          ????Exclude?"type"?from?filter?criterias.

          大概意思是讓你改 filterUsers, 但要注意 DRY(Don't Repeat Yourself)。

          題目內(nèi)置代碼

          interface?User?{
          ??type:?"user";
          ??name:?string;
          ??age:?number;
          ??occupation:?string;
          }

          interface?Admin?{
          ??type:?"admin";
          ??name:?string;
          ??age:?number;
          ??role:?string;
          }

          export?type?Person?=?User?|?Admin;

          export?const?persons:?Person[]?=?[
          ??{
          ????type:?"user",
          ????name:?"Max?Mustermann",
          ????age:?25,
          ????occupation:?"Chimney?sweep",
          ??},
          ??{
          ????type:?"admin",
          ????name:?"Jane?Doe",
          ????age:?32,
          ????role:?"Administrator",
          ??},
          ??{
          ????type:?"user",
          ????name:?"Kate?Müller",
          ????age:?23,
          ????occupation:?"Astronaut",
          ??},
          ??{
          ????type:?"admin",
          ????name:?"Bruce?Willis",
          ????age:?64,
          ????role:?"World?saver",
          ??},
          ??{
          ????type:?"user",
          ????name:?"Wilson",
          ????age:?23,
          ????occupation:?"Ball",
          ??},
          ??{
          ????type:?"admin",
          ????name:?"Agent?Smith",
          ????age:?23,
          ????role:?"Administrator",
          ??},
          ];

          export?const?isAdmin?=?(person:?Person):?person?is?Admin?=>
          ??person.type?===?"admin";
          export?const?isUser?=?(person:?Person):?person?is?User?=>
          ??person.type?===?"user";

          export?function?logPerson(person:?Person)?{
          ??let?additionalInformation?=?"";
          ??if?(isAdmin(person))?{
          ????additionalInformation?=?person.role;
          ??}
          ??if?(isUser(person))?{
          ????additionalInformation?=?person.occupation;
          ??}
          ??console.log(`?-?${person.name},?${person.age},?${additionalInformation}`);
          }

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

          console.log("Users?of?age?23:");

          filterUsers(persons,?{
          ??age:?23,
          }).forEach(logPerson);

          前置知識

          • 泛型
          • Partial 泛型

          思路

          老規(guī)矩, 從報錯入手。

          大概意思是 { age: 23 } 不完整,缺失了部分 key。而題目實(shí)際上的想法應(yīng)該是想根據(jù)部分內(nèi)容對人員進(jìn)行檢錯。比如可以根據(jù) age 查, 也可以根據(jù) name 查,也可以同時根據(jù) age 和 name 查等,這和我們平時的搜索邏輯是一致的。

          直接用 Partial 泛型即可解決, 不懂的可以看下我的文章你不知道的 TypeScript 泛型(萬字長文,建議收藏)。

          代碼

          export?function?filterUsers(persons:?Person[],?criteria:?Partial):?User[]?{
          ????...
          }

          第六題

          題目描述

          Intro:

          ????Filtering?requirements?have?grown.?We?need?to?be
          ????able?to?filter?any?kind?of?Persons.

          Exercise:

          ????Fix?typing?for?the?filterPersons?so?that?it?can?filter?users
          ????and?return?User[]?when?personType='user'?and?return?Admin[]
          ????when?personType='admin'.?Also?filterPersons?should?accept
          ????partial?User/Admin?type?according?to?the?personType.
          ????`criteria`?argument?should?behave?according?to?the
          ????`personType`?argument?value.?`type`?field?is?not?allowed?in
          ????the?`criteria`?field.

          Higher?difficulty?bonus?exercise:

          ????Implement?a?function?`getObjectKeys()`?which?returns?more
          ????convenient?result?for?any?argument?given,?so?that?you?don't
          ????need?to?cast?it.

          ????let?criteriaKeys?=?Object.keys(criteria)?as?(keyof?User)[];
          ????-->
          ????let?criteriaKeys?=?getObjectKeys(criteria);

          大概意思是讓你改 filterUsers, 但要注意 DRY(Don't Repeat Yourself)。并且可以根據(jù) personType 的不同,返回不同的類型。

          題目內(nèi)置代碼

          interface?User?{
          ??type:?"user";
          ??name:?string;
          ??age:?number;
          ??occupation:?string;
          }

          interface?Admin?{
          ??type:?"admin";
          ??name:?string;
          ??age:?number;
          ??role:?string;
          }

          export?type?Person?=?User?|?Admin;

          export?const?persons:?Person[]?=?[
          ??{
          ????type:?"user",
          ????name:?"Max?Mustermann",
          ????age:?25,
          ????occupation:?"Chimney?sweep",
          ??},
          ??{?type:?"admin",?name:?"Jane?Doe",?age:?32,?role:?"Administrator"?},
          ??{?type:?"user",?name:?"Kate?Müller",?age:?23,?occupation:?"Astronaut"?},
          ??{?type:?"admin",?name:?"Bruce?Willis",?age:?64,?role:?"World?saver"?},
          ??{?type:?"user",?name:?"Wilson",?age:?23,?occupation:?"Ball"?},
          ??{?type:?"admin",?name:?"Agent?Smith",?age:?23,?role:?"Anti-virus?engineer"?},
          ];

          export?function?logPerson(person:?Person)?{
          ??console.log(
          ????`?-?${person.name},?${person.age},?${
          ??????person.type?===?"admin"???person.role?:?person.occupation
          ????}
          `

          ??);
          }

          export?function?filterPersons(
          ??persons:?Person[],
          ??personType:?"admin",
          ??criteria:?Partial
          ):?Admin[]
          ;
          export?function?filterPersons(
          ??persons:?Person[],
          ??personType:?"user",
          ??criteria:?Partial
          ):?User[]
          ;
          export?function?filterPersons(
          ??persons:?Person[],
          ??personType:?string,
          ??criteria:?Partial
          ):?Person[]?
          {
          ??return?persons
          ????.filter((person)?=>?person.type?===?personType)
          ????.filter((person)?=>?{
          ??????let?criteriaKeys?=?Object.keys(criteria)?as?(keyof?Person)[];
          ??????return?criteriaKeys.every((fieldName)?=>?{
          ????????return?person[fieldName]?===?criteria[fieldName];
          ??????});
          ????});
          }

          export?const?usersOfAge23?=?filterPersons(persons,?"user",?{?age:?23?});
          export?const?adminsOfAge23?=?filterPersons(persons,?"admin",?{?age:?23?});

          console.log("Users?of?age?23:");
          usersOfAge23.forEach(logPerson);

          console.log();

          console.log("Admins?of?age?23:");
          adminsOfAge23.forEach(logPerson);

          前置知識

          • 泛型
          • Partial 泛型
          • 函數(shù)重載

          思路

          題目描述也懶得看了, 直接看報錯。

          報錯信息提示我們沒有找到合適的函數(shù)重載。因此我的思路就是補(bǔ)上合適的重載即可。關(guān)于函數(shù)重載,我的系列教程不涉及,大家可以看下官網(wǎng)資料。

          重載之后,不同的情況調(diào)用返回值就可以對應(yīng)不同的類型。本題中就是:

          • 如果 personType 是 admin,就會返回 Admin 數(shù)組。
          • 如果 personType 是 user,就會返回 User 數(shù)組。
          • 如果 personType 是其他 string,就會返回 Person 數(shù)組。

          代碼

          export?function?filterPersons(persons:?Person[],?personType:?'admin',?criteria:?Partial):?Admin[]
          export?function?filterPersons(persons:?Person[],?personType:?'user',?criteria:?Partial):?User[]
          export?function?filterPersons(persons:?Person[],?personType:?string,?criteria:?Partial):?Person[]?{
          ????...
          }

          第七題

          題目描述

          Intro:

          ????Filtering?was?completely?removed?from?the?project.
          ????It?turned?out?that?this?feature?was?just?not?needed
          ????for?the?end-user?and?we?spent?a?lot?of?time?just?because
          ????our?office?manager?told?us?to?do?so.?Next?time?we?should
          ????instead?listen?to?the?product?management.

          ????Anyway?we?have?a?new?plan.?CEO's?friend?Nick?told?us
          ????that?if?we?randomly?swap?user?names?from?time?to?time
          ????in?the?community,?it?would?be?very?funny?and?the?project
          ????would?definitely?succeed!

          Exercise:

          ????Implement?swap?which?receives?2?persons?and?returns?them?in
          ????the?reverse?order.?The?function?itself?is?already
          ????there,?actually.?We?just?need?to?provide?it?with?proper?types.
          ????Also?this?function?shouldn'
          t?necessarily?be?limited?to?just
          ????Person?types,?lets?type?it?so?that?it?works?with?any?two?types
          ????specified.

          題目大概意思是讓你修改 swap 函數(shù),使得不報錯。并且,我希望這個函數(shù)可以適用于任意兩個變量,不管其類型一樣不一樣, 也不管二者類型是什么。

          題目內(nèi)置代碼

          interface?User?{
          ??type:?"user";
          ??name:?string;
          ??age:?number;
          ??occupation:?string;
          }

          interface?Admin?{
          ??type:?"admin";
          ??name:?string;
          ??age:?number;
          ??role:?string;
          }

          function?logUser(user:?User)?{
          ??const?pos?=?users.indexOf(user)?+?1;
          ??console.log(`?-?#${pos}?User:?${user.name},?${user.age},?${user.occupation}`);
          }

          function?logAdmin(admin:?Admin)?{
          ??const?pos?=?admins.indexOf(admin)?+?1;
          ??console.log(`?-?#${pos}?Admin:?${admin.name},?${admin.age},?${admin.role}`);
          }

          const?admins:?Admin[]?=?[
          ??{
          ????type:?"admin",
          ????name:?"Will?Bruces",
          ????age:?30,
          ????role:?"Overseer",
          ??},
          ??{
          ????type:?"admin",
          ????name:?"Steve",
          ????age:?40,
          ????role:?"Steve",
          ??},
          ];

          const?users:?User[]?=?[
          ??{
          ????type:?"user",
          ????name:?"Moses",
          ????age:?70,
          ????occupation:?"Desert?guide",
          ??},
          ??{
          ????type:?"user",
          ????name:?"Superman",
          ????age:?28,
          ????occupation:?"Ordinary?person",
          ??},
          ];

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

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

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

          function?test3()?{
          ??console.log("test3:");
          ??const?[secondUser,?firstUser]?=?swap(users[0],?users[1]);
          ??logUser(secondUser);
          ??logUser(firstUser);
          }

          function?test4()?{
          ??console.log("test4:");
          ??const?[firstAdmin,?secondAdmin]?=?swap(admins[1],?admins[0]);
          ??logAdmin(firstAdmin);
          ??logAdmin(secondAdmin);
          }

          function?test5()?{
          ??console.log("test5:");
          ??const?[stringValue,?numericValue]?=?swap(123,?"Hello?World");
          ??console.log(`?-?String:?${stringValue}`);
          ??console.log(`?-?Numeric:?${numericValue}`);
          }

          [test1,?test2,?test3,?test4,?test5].forEach((test)?=>?test());

          前置知識

          • 泛型

          思路

          題目廢話很多, 直接忽略看報錯。

          這個其實(shí)我在 你不知道的 TypeScript 泛型(萬字長文,建議收藏) 里也講過了,直接看代碼。

          代碼

          export?function?swap<U,?T>(v1:?T,?v2:?U):?[U,?T]?{
          ??return?[v2,?v1];
          }

          第八題

          題目描述

          Intro:

          ????Project?grew?and?we?ended?up?in?a?situation?with
          ????some?users?starting?to?have?more?influence.
          ????Therefore,?we?decided?to?create?a?new?person?type
          ????called?PowerUser?which?is?supposed?to?combine
          ????everything?User?and?Admin?have.

          Exercise:

          ????Define?type?PowerUser?which?should?have?all?fields
          ????from?both?User?and?Admin?(except?for?type),
          ????and?also?have?type?'powerUser'?without?duplicating
          ????all?the?fields?in?the?code.

          題目大概意思是定義一個類型 PowerUser, 里面包含 User 和 Admin 的所有屬性, 并且有一個字段是固定的 type: 'powerUser'。

          題目內(nèi)置代碼

          interface?User?{
          ??type:?"user";
          ??name:?string;
          ??age:?number;
          ??occupation:?string;
          }

          interface?Admin?{
          ??type:?"admin";
          ??name:?string;
          ??age:?number;
          ??role:?string;
          }

          type?PowerUser?=?Omit"type">?&?{?type:?"powerUser"?};

          export?type?Person?=?User?|?Admin?|?PowerUser;

          export?const?persons:?Person[]?=?[
          ??{
          ????type:?"user",
          ????name:?"Max?Mustermann",
          ????age:?25,
          ????occupation:?"Chimney?sweep",
          ??},
          ??{?type:?"admin",?name:?"Jane?Doe",?age:?32,?role:?"Administrator"?},
          ??{?type:?"user",?name:?"Kate?Müller",?age:?23,?occupation:?"Astronaut"?},
          ??{?type:?"admin",?name:?"Bruce?Willis",?age:?64,?role:?"World?saver"?},
          ??{
          ????type:?"powerUser",
          ????name:?"Nikki?Stone",
          ????age:?45,
          ????role:?"Moderator",
          ????occupation:?"Cat?groomer",
          ??},
          ];

          function?isAdmin(person:?Person):?person?is?Admin?{
          ??return?person.type?===?"admin";
          }

          function?isUser(person:?Person):?person?is?User?{
          ??return?person.type?===?"user";
          }

          function?isPowerUser(person:?Person):?person?is?PowerUser?{
          ??return?person.type?===?"powerUser";
          }

          export?function?logPerson(person:?Person)?{
          ??let?additionalInformation:?string?=?"";
          ??if?(isAdmin(person))?{
          ????additionalInformation?=?person.role;
          ??}
          ??if?(isUser(person))?{
          ????additionalInformation?=?person.occupation;
          ??}
          ??if?(isPowerUser(person))?{
          ????additionalInformation?=?`${person.role},?${person.occupation}`;
          ??}
          ??console.log(`${person.name},?${person.age},?${additionalInformation}`);
          }

          console.log("Admins:");
          persons.filter(isAdmin).forEach(logPerson);

          console.log();

          console.log("Users:");
          persons.filter(isUser).forEach(logPerson);

          console.log();

          console.log("Power?users:");
          persons.filter(isPowerUser).forEach(logPerson);

          前置知識

          • 集合操作(交叉類型)
          • & 操作符
          • 泛型
          • Omit 泛型

          思路

          從題目信息不難看出,就是讓我們實(shí)現(xiàn) PowerUser。

          有前面的分析不難得出我們只需要:

          • 合并 User 和 Admin 的屬性即可。借助 & 操作符可以實(shí)現(xiàn)。即 User & Admin
          • 增加特有的屬性 type: powerUser。首先去掉上一步合并的 type 屬性, 然后繼續(xù)和 { type: "powerUser" } 交叉即可。
          • 增加 { type: "powerUser" } 之前使用內(nèi)置泛型 Omit 將原本的 type 刪掉即可。

          代碼

          type?PowerUser?=?Omit"type">?&?{?type:?"powerUser"?};

          總結(jié)

          以上就是給大家?guī)淼念}目解析。這八道題的考點(diǎn)有,按照我個人理解的重要程度劃分為:

          • type 和 interface 的基本操作(必須掌握)
          • 聯(lián)合類型 和 交叉類型(強(qiáng)烈建議掌握)
          • 類型斷言和類型收縮(強(qiáng)烈建議掌握)
          • 泛型和常見內(nèi)置泛型(強(qiáng)烈建議掌握)
          • 函數(shù)重載(推薦掌握)

          最后祝愿大家告別 anyscript,成為 TypeScript 魔法師

          Reference

          [1]

          深入理解 TypeScript: https://jkchao.github.io/typescript-book-chinese/

          [2]

          TypeScript 官方文檔: https://www.typescriptlang.org/docs/home

          [3]

          typescript-exercises: https://typescript-exercises.github.io/

          推薦閱讀


          1、NPM 組件你應(yīng)該知道的事

          2、你不知道的 TypeScript 泛型(萬字長文,建議收藏)

          3、尤大 3 天前發(fā)在 GitHub 上的 vue-lit 是啥?

          4、字節(jié)跳動的算法面試題是什么難度?



          如果覺得文章不錯,幫忙點(diǎn)個在看唄





          瀏覽 48
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国模掰逼 | 91AV电影网 | 亚洲精品一线二线三线 | 欧美操毕视频 | 亚洲人xxxxc |