比較基礎的TypeScript概念,以我能力所及,已經提的差不多了QQ
那接下來就讓我們看看要怎麼在React中加上TypeScript吧!
相信前面十幾天的文章,你已經學會/至少知道如何描述一個變數/物件的型別,我們主要沒帶到的大概就是JavaScript的class
類別了。(在當今React世界中,class components已經是比較少人會使用的寫法(儘管他有其無可取代性),相對的,後來產生的Functional component逐漸成為主流,Hook的引入也使得React的門檻稍稍降低了一些,所以沒提到class應該不影響後續學習。)
接下來幾天,我們會開始在React中練習加上TypeScript,這邊建議你在本地端架一個已經有TypeScript樣板的React專案,指令如下:
> npx create-react-app my-app --template typescript
//或是
> yarn create react-app my-app --template typescript
TypeScript樣版的React安裝完畢後,我們就能看到src資料夾內,App從原本js副檔名,轉變成了tsx副檔名,接著我們就能開始使用了!
今天我們講個簡單的useState就好
讓我們直接在App.tsx內寫點東西吧,首先我們來寫個useState
會讀到這邊的你,早就知道useState()
函式內要放的是什麼了,就是個起始值,它可以是原始值,也可以是物件,甚至可以是一個callback function。
在.tsx內
import {useState} from 'react' //記得引入喔
function App(){
const [count, setCount] = useState(0)
const onClick = () => {
setCount(prevCount=>prevCount + 1)
}
return (
<div className="App">
<span>{count}</span>
<button onClick={onClick}>Hi</button>
</div>
)
}
從上面的程式碼來看,我們雖然沒有明確寫出count
的型別,但TypeScript已經從起始值幫我們推測count
是number
了,所以後續我們在我們自定義的onClick
函式裡面,對每次的點擊進行+1
,也是合法不會報錯的。
那我們把onClick
內的setCount
換成別的東西試試看
const onClick = () => {
setCount("no count")
}
這時就會看到TypeScript報錯了:
類型 'string' 的引數不可指派給類型 'SetStateAction<number>' 的參數
那麼,如果我們真的需要讓count的型別,有時是數字,而有時又是字串,該怎麼做呢?就主動註記型別吧:
const [count, setCount] = useState<string | number>(0)
const onClick = () => {
setCount("no count")
}
這樣子TypeScript就不會報錯了,因為count
現在已經被使用者判定為可能會是字串也可能會是數字了。
我們也能運用先前講到的型別別名,也能解決一樣的問題:
type Count = string | number
const [count, setCount] = useState<Count>(0)
const onClick = () => {
setCount("no count")
}
假如起始值是個物件,後續更新變數的規則也是差不多的:
interface Count {
value: number
}
function App() {
//我知道寫法有點醜,但...會習慣的
const [count, setCount] = useState<Count | null>({ value: 0 })
const onClick = () => {
setCount(null)
}
return (
<div className="App">
<span>{count && count.value}</span>
<button onClick={onClick}>Hi</button>
</div>
)
}
在上面的程式碼中,我們將count
起始值設定為一個物件{value: 0}
,所以TypeScript就會預設你之後的count
,形狀都會是{value: number}
。若我們想要在後續讓他變成null
,甚至是起始值讓他為null
而後續變成{value: number}
,就在創立前為他進行型別聯集的宣告<Count | null>
,就可以了。
這邊值得注意的是,由於count
可能是一個有value
的物件、也可能是null
,所以我們在return
JSX時,必須確認count
非null
時,才能正確渲染count.value
,若直接寫<span>{count.value}</span>
,TypeScript就會噴錯!
由簡單的例子出發,我們就能知道,要是在一開始有主動去宣告型別,在後續便能避免我們自己(或同事)意外的將某變數修改為錯的型別,大大減少後續debug的時間,且在React當中,我們有很大機率會將count
跟setCount
當做props
給傳到子層去,沒有TypeScript的話,我們容易降低對變數的掌握度。建議大家可以練習看看將useState
的初始值設定成更加複雜的型態(當然你也可以改成使用useReducer
啦,不過這我們後面會講到),就能體會到TypeScript的優點囉。