在 React 中使用 TypeScript

Create React App 內(nèi)置了對(duì) TypeScript 的支持。
需要?jiǎng)?chuàng)建一個(gè)使用 TypeScript 的新項(xiàng)目,在終端運(yùn)行:
npx create-react-app my-app --template typescriptReact 中,你的組件文件大多數(shù)使用 .js 作為擴(kuò)展名。在 TypeScript 中,提供兩種文件擴(kuò)展名:
.ts 是默認(rèn)的文件擴(kuò)展名,而 .tsx 是一個(gè)用于包含 JSX 代碼的特殊擴(kuò)展名。
類型定義
為了能夠顯示來自其他包的錯(cuò)誤和提示,編譯器依賴于聲明文件。聲明文件提供有關(guān)庫的所有類型信息。這樣,我們的項(xiàng)目就可以用上像 npm 這樣的平臺(tái)提供的三方 JavaScript 庫。
獲取一個(gè)庫的聲明文件有兩種方式:
Bundled - 該庫包含了自己的聲明文件。這樣很好,因?yàn)槲覀冎恍枰惭b這個(gè)庫,就可以立即使用它了。要知道一個(gè)庫是否包含類型,看庫中是否有 index.d.ts 文件。有些庫會(huì)在 package.json 文件的 typings 或 types 屬性中指定類型文件。
DefinitelyTyped - DefinitelyTyped 是一個(gè)龐大的聲明倉庫,為沒有聲明文件的 JavaScript 庫提供類型定義。這些類型定義通過眾包的方式完成,并由微軟和開源貢獻(xiàn)者一起管理。例如,React 庫并沒有自己的聲明文件。但我們可以從 DefinitelyTyped 獲取它的聲明文件。只要執(zhí)行以下命令。
# yarnyarn add --dev @types/react# npmnpm i --save-dev @types/react
局部聲明 - 有時(shí),你要使用的包里沒有聲明文件,在 DefinitelyTyped 上也沒有。在這種情況下,我們可以創(chuàng)建一個(gè)本地的定義文件。因此,在項(xiàng)目的根目錄中創(chuàng)建一個(gè) declarations.d.ts 文件。一個(gè)簡(jiǎn)單的聲明可能是這樣的:
declare module 'querystring' {export function stringify(val: object): stringexport function parse(val: string): object}
現(xiàn)在已做好編碼準(zhǔn)備了!下面開始項(xiàng)目實(shí)戰(zhàn)來了解有關(guān) TypeScript 的更多知識(shí):
// store.tsximport { createStore, applyMiddleware, StoreEnhancer, StoreEnhancerStoreCreator, Store } from 'redux'import thunk from 'redux-thunk'import reducer from './reducers'let storeEnhancer:StoreEnhancer = applyMiddleware(thunk)let storeEnhancerStoreCreator:StoreEnhancerStoreCreator = storeEnhancer(createStore)let store: Store = storeEnhancerStoreCreator(reducer)export default store
// reducers/index.tsximport { combineReducers, ReducersMapObject, AnyAction, Reducer } from 'redux'import counter, { CounterState} from './count'//接口其實(shí)就是定義合并后的狀態(tài)export interface CombinedState {counter1: CounterState}let reducers:ReducersMapObject<CombinedState, AnyAction> = {counter1: counter}let reducer:Reducer<CombinedState, AnyAction> = combineReducers(reducers)export default reducer
// reducers/count.tsximport { AnyAction } from "redux";export interface CounterState {count: number}const initialState: CounterState = {count: 0}export default function reducer(state: CounterState = initialState, action: AnyAction): CounterState {console.log(action)switch (action.type) {case 'ADD':return { count: state.count + 1 }default:return state}}
// index.tsximport React from 'react';import ReactDOM from 'react-dom';import './index.css';import Counter from './components/Counter';import reportWebVitals from './reportWebVitals';import { Provider } from 'react-redux'import store from './store'ReactDOM.render(<Provider store={store}><Counter /></Provider>,document.getElementById('root'))
// components/Counter.tsximport React from 'react'import { Dispatch } from 'redux'import { connect } from 'react-redux'import { CounterState } from '../store/reducers/count'import { CombinedState } from '../store/reducers'let mapStateToProps = (state:CombinedState):CounterState => state.counter1let mapDispatchToProps = (dispatch: Dispatch) => {return {add () { dispatch({ type: 'ADD' }) }}}type Props = ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps>class Counter extends React.Component<Props> {render () {return (<div><button onClick={() => this.props.add()}>加</button><div>{this.props.count}</div></div>)}}export default connect(mapStateToProps, mapDispatchToProps)(Counter)
創(chuàng)建 store 狀態(tài)管理我們需要安裝的包:
npm i react-redux redux-thunk --savenpm i @types/react-redux --save-dev簡(jiǎn)單的代碼演示介紹到這里,你學(xué)會(huì)了嗎?
