I
的理由→ TS 本身就已達成標注型別的目的
// 如果帕斯卡命名法對你來說合理... interface IUser { name: string } // 那何不也這麼做? const SName = 'Sean' // "S" for String const NAge = 18 // "N" for Number const AFriends = [/*...*/] // "A" for Array
interface
和 type
若前綴 I
僅是為了註明它是個 Interface…
🌰
分別以不同的方式宣告型別 User
// A. interface IUser { name: string } interface IUser { age: number }
// B. type TUser = { name: string, age: number }
// C. type RUser = Record<'name', string> & Record<'age', number>
TypeScript 是🦆鴨子型別
(Duck Typing)
當看到一隻鳥走起來像🦆、
游泳起來像🦆、
叫起來也像🦆,
那麼這隻鳥就可以被稱為🦆
型別總是以大駝峰命名
type User = {
name: string,
age: number,
}
而變數總是以小駝峰命名
const user: User = {
name: 'Sean',
age: 23,
}
→ 容易混淆,一時難以分辨它是組件或是型別
🌰
import Dialog from '@material-ui/core/Dialog' interface Dialog { // ^^^^^^ 🥲 'Dialog' is already defined 'delete': DialogContent, 'deleteForbidden': DialogContent, 'deactivate': DialogContent, }
interface DialogContents { /*...*/ } // 👍
🌰
MUI 的 Pagination 組件(節錄)
// @material-ui/lab/Pagination/Pagination.d.ts interface PaginationProps { color?: 'primary' | 'secondary' | 'standard' } function Pagination( props: PaginationProps ): JSX.Element;
變數名 | 型別名 |
---|---|
props |
PaginationProps 或 Props |
state |
DialogState 或 State |
💡 可根據上下文
自行決定是否省略修飾語
🌰(節錄)
const handleClose = ( event?: React.SyntheticEvent, // 🤔 reason?: string // 😑 ) => { /* ... */ }
<Snackbar onClose={handleClose} />
運氣好的話
你會看到這個已匯出的型別定義
匯入
import Snackbar, { SnackbarProps } from '@material-ui/core/Snackbar'
指定 handler 的型別
const handleClose: SnackbarProps['onClose'] = ( event, // React.SyntheticEvent<any, Event> reason, // SnackbarCloseReason ) => { /* ... */ }
🎉 得到符合組件要求的參數型別
<Snackbar onClose={handleClose} />
src/constants/type.ts
→ 抽出型別成獨立檔案並置於 src/types
例如 Controller.ts
、Model.ts
K7 建議:目錄結構請參考 container 和 component
→ 只用 BS 的網格相關 class 如 .row
、 .col
、 .container
等;
其餘用 MUI 的組件如 <Box />