面試官:說說如何在React項目中應用TypeScript
一、前言
單獨的使用typescript 并不會導致學習成本很高,但是絕大部分前端開發(fā)者的項目都是依賴于框架的
例如和vue、react 這些框架結合使用的時候,會有一定的門檻
使用 TypeScript 編寫 react 代碼,除了需要 typescript 這個庫之外,還需要安裝@types/react、@types/react-dom
- npm i @types/react -s
 - npm i @types/react-dom -s
 
至于上述使用@types的庫的原因在于,目前非常多的javascript庫并沒有提供自己關于 TypeScript 的聲明文件
所以,ts并不知道這些庫的類型以及對應導出的內容,這里@types實際就是社區(qū)中的DefinitelyTyped庫,定義了目前市面上絕大多數的JavaScript庫的聲明
所以下載相關的javascript對應的@types聲明時,就能夠使用使用該庫對應的類型定義
二、使用方式
在編寫react項目的時候,最常見的使用的組件就是:
- 無狀態(tài)組件
 - 有狀態(tài)組件
 - 受控組件
 
無狀態(tài)組件
主要作用是用于展示UI,如果使用js聲明,則如下所示:
- import * as React from 'react'
 - export const Logo = props => {
 - const { logo, className, alt } = props
 - return (
 - <img src={logo} className={className} alt={alt} />
 - )
 - }
 
但這時候ts會出現報錯提示,原因在于沒有定義porps類型,這時候就可以使用interface接口去定義porps即可,如下:
- import * as React from 'react'
 - interface IProps {
 - logo?: string
 - className?: string
 - alt?: string
 - }
 - export const Logo = (props: IProps) => {
 - const { logo, className, alt } = props
 - return (
 - <img src={logo} className={className} alt={alt} />
 - )
 - }
 
但是我們都知道props里面存在children屬性,我們不可能每個porps接口里面定義多一個children,如下:
- interface IProps {
 - logo?: string
 - className?: string
 - alt?: string
 - children?: ReactNode
 - }
 
更加規(guī)范的寫法是使用React里面定義好的FC屬性,里面已經定義好children類型,如下:
- export const Logo: React.FC<IProps> = props => {
 - const { logo, className, alt } = props
 - return (
 - <img src={logo} className={className} alt={alt} />
 - )
 - }
 
- React.FC顯式地定義了返回類型,其他方式是隱式推導的
 - React.FC對靜態(tài)屬性:displayName、propTypes、defaultProps提供了類型檢查和自動補全
 - React.FC為children提供了隱式的類型(ReactElement | null)
 
有狀態(tài)組件
可以是一個類組件且存在props和state屬性
如果使用typescript聲明則如下所示:
- import * as React from 'react'
 - interface IProps {
 - color: string,
 - size?: string,
 - }
 - interface IState {
 - count: number,
 - }
 - class App extends React.Component<IProps, IState> {
 - public state = {
 - count: 1,
 - }
 - public render () {
 - return (
 - <div>Hello world</div>
 - )
 - }
 - }
 
上述通過泛型對props、state進行類型定義,然后在使用的時候就可以在編譯器中獲取更好的智能提示
關于Component泛型類的定義,可以參考下 React 的類型定義文件 node_modules/@types/react/index.d.ts,如下所示:
- class Component<P, S> {
 - readonly props: Readonly<{ children?: ReactNode }> & Readonly<P>;
 - state: Readonly<S>;
 
從上述可以看到,state屬性也定義了可讀類型,目的是為了防止直接調用this.state更新狀態(tài)
受控組件
受控組件的特性在于元素的內容通過組件的狀態(tài)state進行控制
由于組件內部的事件是合成事件,不等同于原生事件,
例如一個input組件修改內部的狀態(tài),常見的定義的時候如下所示:
- private updateValue(e: React.ChangeEvent<HTMLInputElement>) {
 - this.setState({ itemText: e.target.value })
 - }
 
常用Event 事件對象類型:
- ClipboardEvent
剪貼板事件對象  - DragEvent
拖拽事件對象  - ChangeEvent
Change 事件對象  - KeyboardEvent
鍵盤事件對象  - MouseEvent
鼠標事件對象  - TouchEvent
觸摸事件對象  - WheelEvent
滾輪事件對象  - AnimationEvent
動畫事件對象  - TransitionEvent
過渡事件對象  - T接收一個DOM 元素類型
 
三、總結
上述只是簡單的在react項目使用typescript,但在編寫react項目的時候,還存在hooks、默認參數、以及store等等......
typescript在框架中使用的學習成本相對會更高,需要不斷編寫才能熟練
參考文獻
https://juejin.cn/post/6952696734078369828
                          
https://juejin.cn/post/6844903684422254606
















 
 
 







 
 
 
 