在 React 中使用 TypeScript
共 3597字,需浏览 8分钟
·
2021-03-16 17:41
Create React App 内置了对 TypeScript 的支持。
需要创建一个使用 TypeScript 的新项目,在终端运行:
npx create-react-app my-app --template typescript
React 中,你的组件文件大多数使用 .js
作为扩展名。在 TypeScript 中,提供两种文件扩展名:
.ts
是默认的文件扩展名,而 .tsx
是一个用于包含 JSX 代码的特殊扩展名。
类型定义
为了能够显示来自其他包的错误和提示,编译器依赖于声明文件。声明文件提供有关库的所有类型信息。这样,我们的项目就可以用上像 npm 这样的平台提供的三方 JavaScript 库。
获取一个库的声明文件有两种方式:
Bundled - 该库包含了自己的声明文件。这样很好,因为我们只需要安装这个库,就可以立即使用它了。要知道一个库是否包含类型,看库中是否有 index.d.ts
文件。有些库会在 package.json
文件的 typings 或 types 属性中指定类型文件。
DefinitelyTyped - DefinitelyTyped 是一个庞大的声明仓库,为没有声明文件的 JavaScript 库提供类型定义。这些类型定义通过众包的方式完成,并由微软和开源贡献者一起管理。例如,React 库并没有自己的声明文件。但我们可以从 DefinitelyTyped 获取它的声明文件。只要执行以下命令。
# yarn
yarn add --dev @types/react
# npm
npm i --save-dev @types/react
局部声明 - 有时,你要使用的包里没有声明文件,在 DefinitelyTyped 上也没有。在这种情况下,我们可以创建一个本地的定义文件。因此,在项目的根目录中创建一个 declarations.d.ts 文件。一个简单的声明可能是这样的:
declare module 'querystring' {
export function stringify(val: object): string
export function parse(val: string): object
}
现在已做好编码准备了!下面开始项目实战来了解有关 TypeScript 的更多知识:
// store.tsx
import { 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.tsx
import { combineReducers, ReducersMapObject, AnyAction, Reducer } from 'redux'
import counter, { CounterState} from './count'
//接口其实就是定义合并后的状态
export interface CombinedState {
counter1: CounterState
}
let reducers:ReducersMapObject<CombinedState, AnyAction> = {
counter1: counter
}
let reducer:Reducer<CombinedState, AnyAction> = combineReducers(reducers)
export default reducer
// reducers/count.tsx
import { 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.tsx
import 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.tsx
import 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.counter1
let 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)
创建 store 状态管理我们需要安装的包:
npm i react-redux redux-thunk --save
npm i @types/react-redux --save-dev
简单的代码演示介绍到这里,你学会了吗?