# [React] React with TypeScript 筆記 ###### tags `React` `TypeScript` `前端筆記` <div style="display: flex; justify-content: flex-end"> > created: 2024/07/22 </div> ## 說明 記錄 React 使用 TypeScript 的一些學習筆記。 ## `React.ComponentPropsWithoutRef<HTMLElement>` 讓 Component 可以有對應 HTMLElement 的屬性 > 關鍵字:`Wrapping/Mirroring a HTML Element` 若想要建立一個按鈕元件,但是又想要讓該元件可以有原生 `<butto />` 的屬性的話,可以使用 `React.ComponentPropsWithoutRef<HTMLElement>` 在使用該元件時也可以透過 `props` 傳入對應 HTMLElement 的屬性: ```typescript= // ref. https://react-typescript-cheatsheet.netlify.app/docs/advanced/patterns_by_usecase/#wrappingmirroring import * as React from 'react'; // usage function App() { // Type '"foo"' is not assignable to type '"button" | "submit" | "reset" | undefined'.(2322) // return <Button type="foo"> sldkj </Button> // no error return <Button type='button'> text </Button> } // implementation 1 // export interface ButtonProps extends React.ComponentProps<'button'> { // specialProp?: string; // } // implementation 2 type ButtonProps = { specialProp?: string } & React.ComponentPropsWithoutRef<'button'> export function Button(props: ButtonProps) { const { specialProp, ...rest } = props; // do something with specialProp return <button {...rest} />; } ``` [TS Playground](https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcA5FDvmQNwCwAUIwPTNwCuqyA5lowewB2+YBEFwAgmDAAKAJRwA3ozhxWcACoBPMFnIAiAhAj6ycYOkER4aVMG6DkAIwA2emBDgwdesvqfsMB6C+nAAPnD6qOxOIMAwoRH6lKhYCeEcggAmWATAglhZZAB0MgBMAMxlZXIqamyUMOxQ4gA8AEKBwV4+ALyGxvoAfHCoLlkA1gBWcK3MnUFiQ3V16lZwWFDEUHWNzW0L3d66vWQBi4JkIzBYAB7wc4dLjAC+jCxsoGBuIFiCMMgYKJBB8NrdILBzP9NgQ8HonoIAArEMDoO43bLobB4GDFADCJEgBX+yIgqNaZy6YiuSlBqlQulwwGQLlJYAA-AAuUYwKD5bj0BjqN5MIWfcA-P4AoFiOBlOCMY7wqlIlHoXq0hj0xnM1kork8vmCbivOAAMkwVFxBPAYilbNQAHV4gALCCBbAECnnYJXd5i8wSrC-f6A4FwCpwXojEDQPQAN02TggqQVAaVcARDqjmvU2qwTJZbINqF5-NBL3NlpxxQRAAkNABZAAyEiCfPOWFQrQbLYRAFFJf9lqLGHcIYQhCJZQiZGA1dys2qFMotXBcGJS0pRjqiyiADRwYrHlLwSsa+dk1CC1TqLKeVAkNIu-lwADurp3Bd1bN2aX2sw+rKijHsUp6VswQyCi8QA) :::info 有 `React.ComponentPropsWithoutRef` 當然也就有 `React.ComponentPropsWithRef` 差別是有無 `props.ref`。 ::: ## `type` vs `interface` > Type aliases and interfaces are very similar, and in many cases you can choose between them freely. Almost all features of an `interface` are available in `type`, the key distinction is that a type cannot be re-opened to add new properties vs an interface which is always extendable. > *[ref. Differences Between Type Aliases and Interfaces](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#differences-between-type-aliases-and-interfaces)* 基本上 `interface` 跟 `type` 的使用時機沒有硬性規定,這兩個方式都可以達到定義物件該長怎麼樣。差別是這兩個都有自己的限制: ### `inteface` 1. 不可用 `intersection(&)` 只能用 `extends` ```typescript= interface HtmlAttributes { disabled: boolean } interface ButtonHtmlAttributes extends HtmlAttributes { type: 'Submit' | 'Button' | null } ``` 2. 重複名稱的 `interface` 會自動 merge ```typescript= interface Test { title: string; } interface Test { ts: number; } let test: Test = { title: '', ts: 9 } ``` [TS Playground](https://www.typescriptlang.org/play/?#code/JYOwLgpgTgZghgYwgAgBJgLYBsCCYxTABGArpAM7IDeAsAFDLIAmw5cRWETAXMkQPb9OcEPQC+9SXVCRYiFACEyYfiHTY8BYmQiUIAD0ggmldbnyFSFavUZgAngAcIvAOQBlEkQzAwr5AA+yK5K+Kr+QSAkWFjiUjLQ8EjIACq6YDYMyGC+nLzkWiAA5gDccXT0CXLJaQWZduS8URhE0GV0EhV0nBkUYLy1GQC89dm5LsGuADS22Y3IAJziQA) ### `type` 1. 不可用 `extends` 只能用 `intersection(&)` ```typescript= type HtmlAttributes = { disabled: boolean } type ButtonHtmlAttributes = { type: 'Submit' | 'Button' | null } & HtmlAttributes ``` 2. `interface` 只能定義物件,但是 `type` 可以很活 ```typescript= type isLoading = boolean type Theme = "dark" | "light" type Lang = "en" | "fr" ``` 3. 不會像 `interface` 一樣自動 merge 相同名稱的 `interface` ```typescript= type TestError = { name: string } // Duplicate identifier 'TestError'.(2300) type TestError = { age: number } ``` [TS Playground](https://www.typescriptlang.org/play/?#code/C4TwDgpgBAEsC2AbAgsYAnAlgIwK7AgGcoBeKAbwFgAoKKAE00IENtEJ6AuKbAe1-bMAdjQC+NGqEhQAQvmC8hcJKgw58RUhRp0pEbgHIAyrmzxMwA1AA+UA3LSKrtobkSIxUAGSwEKNFh4BIQS1HpQTAAyvMyMQgDmWnwCEMKS4NAAKgAWEPDQZABE9MzoANaFNlCFiJjx2cCF6dKRwolFEEKVtoUAZuhN1M1ZRMAAoujovOhaVLRQQsz53IRqCWKh4ZmjE1MzZHN0zPH6C7jw2BDoG9RAA) ## 參考資料 1. [React with TypeScript Cheatsheet](https://blog.bitsrc.io/react-with-typescript-cheatsheet-9dd891dc5bfe#d41e)
×
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