# 🏅 Day 17 - Promise 非同步設計 我們在開發時,很常會需要使用到非同步技術,來開發前後端功能,所以今天來分享一下 promise 吧 :D 當在 TypeScript 中使用 Promise 時,你可以透過泛型來指定 Promise 被解析出來的型別。藉此獲得型別提示跟檢查。 ### promise 情境 當我們寫一個 promise 時,會寫成如下程式碼: ```=tsx const promise = new Promise((resolve) => { setTimeout(() => { resolve('hello!'); }, 2000); }); promise.then((data) => { data.split(''); }); ``` 當我們滑鼠滑到 `resolve` 參數時,會被告知,目前他的型別為 `unknown`  那麼 `unknown` 是什麼呢? ## 小教室:unknown 是什麼?又跟 any 有什麼差別 `unknown` 型別也是任意值的意思,那麼和 `any` 的差別在哪呢? 在使用 `unknown` 型別進行屬性方法操作時,必須在那之前進行型別檢查或斷言才會正常,如下程式碼: ```=tsx // 使用 any 型別 let valueAny: any = "Hello, world!"; console.log(valueAny.length); // 正常 // 使用 unknown 型別 let valueUnknown: unknown = "Hello, world!"; // 嘗試直接訪問 unknown 型別會導致編譯錯誤 // console.log(valueUnknown.length); // 編譯錯誤 // 會告知型別“unknown”上不存在屬性“length” // 進行型別檢查 if (typeof valueUnknown === "string") { console.log(valueUnknown.length); // 經過型別檢查後才會允許讀取方法 } ``` 所以相較而言來說,`unknown` 嚴謹性較高,以下提供比較表格 | 特性 | any | unknown | | --- | --- | --- | | 安全性 | 低 (無限制) | 高 (受限制) | | 型別檢查需求 | 無需型別檢查 | 需要型別檢查或斷言 | | 操作限制 | 無限制 | 受限,直到型別被確認 | | 維護性和可讀性 | 較低 | 較高 | ## 加入型別註釋 promise 泛型來優化 ```tsx= const promise: Promise<string> = new Promise((resolve) => { setTimeout(() => { resolve('hello!'); }, 1000); }); ``` 此時滑鼠滑過去 `resolve` 參數裡面就會被定義為字串型別 ### 情境:使用 fetch API 來獲得使用者資訊 假設我們要從一個 API 取得一些使用者資料,這個資料可以用一個介面來描述: ```tsx= interface User { id: number; name: string; } ``` 當一個函式需要回傳一個 Promise 時,寫法如下,解析後的型別則定義是 **`User`** 介面,來提升可讀性: ```tsx function getUser(id: number): Promise<User> { return fetch(`https://someapi.com/users/${id}`) .then(response => response.json()) .then(data => data); } ``` ## **結合 async 與 await** 當使用 **`async`** 和 **`await`** 時,TypeScript 能夠從你 **`await`** 的表達式中推斷出回傳值的型別。 ### 範例程式碼: 將剛才的 **`getUser`** 函式在另一個 async 函式中使用: ```tsx= interface User { id: number; name: string; } function getUser(id: number): Promise<User> { return fetch(`https://someapi.com/users/${id}`) .then(response => response.json()) .then(data => data); } async function showUserName(id: number) { const user = await getUser(id); // user 會顯示回傳 User 介面 console.log(`使用者名稱:${user.name}`); } ``` 藉由我們定義了 Promise 泛型後,滑鼠指向 14 行的 user 變數時,型別檢查器就會告知該型別為 `User` 介面,並讓後續的程式碼享有型別檢查的好處,例如在訪問 `user.name` ,也能知道裡面定義的型別是字串型別   # 開發題 請隨意挑選 TodoList 裡面任一個 API,來加上 Promise 泛型,例如註冊 API、todo API,可參考 Day 16 [苡安同學](https://stackblitz.com/edit/vitejs-vite-qjrf7o?file=src%2Fstores%2FTodoStore.ts%3AL12)的 Promise API 請求搭配 `Todo[]` 1. API 網址:https://todolist-api.hexschool.io/ 2. API 文件:https://todolist-api.hexschool.io/doc/ 回報區 --- | Discord | CodePen / 答案 | |:-------------:|:----------------------------------------------------------------:| |洧杰|[Codepen](https://codepen.io/hexschool/pen/poYgYqW?editors=1010)| |HsienLu|[Codepen](https://codepen.io/Hsienlu/pen/QWoaXKo?editors=1011)| |苡安|[Codepen](https://codepen.io/yi-an-yang/pen/zYbpVRK)| |展誠|[CodePen](https://codepen.io/hedgehogkucc/pen/jOJZOgP?editors=1012)| |shaokang|[CodePen](https://stackblitz.com/edit/vitejs-vite-3hq2pq?file=src%2Fmain.tsx,src%2Findex.css,src%2FSignUp.tsx,src%2FSignUp.css&terminal=dev)| |hannahTW|[CodePen](https://codepen.io/hangineer/pen/zYbRqvM?editors=0011)| |wei|[codePen](https://codepen.io/jweeei/pen/RwdQaGr?editors=1010)| |erwin阿瀚|[CodePen](https://codepen.io/yohey03518/pen/OJqvdXy?editors=1111) |claire chang|[CodePen](https://codepen.io/claire-chang-the-bashful/pen/OJqvqQQ) |rikku1756|[CodePen](https://codepen.io/rikkubook/pen/BabVzMJ)
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up