开发经验-TS日常经验

346 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

作者:王哲弘

1、索引签名的参数类型不能是联合类型

type Key = 'foo' | 'test';
type IndexType = {
  [prop: Key]: number | string;
}
let obj: IndexType = {
  foo: 1,
  test: 'hello'
}
obj['test'] = 'hahaha';

以上代码编译时会出现以下警告:

TS1337: An index signature parameter type cannot be a union type. Consider using a mapped object type instead.

我们需要改写IndexType 类型,如何修改呢?上面的警告已经给出提示,那就是使用映射类型代替:

type IndexType = {     [p in Key]:  number | string; }

\

2、redux state 类型定义时不要写成可选属性(以下是错误示范)

export interface ModifyGrades {
  savedList?: ModifyItem[]; // 已保存的修改记录列表
  groups?: Groups[]; // 题型数据
  questions?:Question[];
  subjectLists?: Subject[];
  summaryId?: number;
  studentAnswers?: StudentAnswers;
  title?: string; //业务头额外标题
}

正确的做法是在某组件需要的时候使用映射类型进行转换(ts中已经定义了Partial类型,可以直接使用) 如下\

interface ModifyGrades {
  savedList: ModifyItem[]; // 已保存的修改记录列表
  groups: Groups[]; // 题型数据
  questions:Question[];
  subjectLists: Subject[];
  summaryId: number;
  studentAnswers: StudentAnswers;
  title: string; //业务头额外标题
}
type Props = Partial<ModifyGrades>

Partial类型如下:

type Partial<T> = {
  [P in keyof T]?: T[P];
}

3、...props 属性传递的时子组件类型可以从父组件中导入继承

// Father.tsx
import React, {FC} from 'react';
import Child from './Child';
import Other from './Other';
export interface FatherProps {
  name: string;
  age: number;
  desc: string;
}
const Father: FC<FatherProps> = (props) => <div>
  <Child {...props}/>
  <Other/>
  </div>;
export default Father;


//Child.tsx
import React, {FC} from 'react';
import {FatherProps} from './Father';

interface ChildProps extends FatherProps {
  //子组件其他的props(例如connect方法中获取的)
}
const Father: FC<ChildProps> = (props) => <div>
  {/* 子组件的具体内容 */}
  </div>;
export default Child;

这种继承父组件的类型,在修改父组件的props时候无需再修改子组件props类型

4、redux 相关系列

概念:

(1)、dispatch方法,唯一的修改redux state的方法,接收的参数是action

(2)、action为纯对象,拥有标识类型type属性

(3)、reducers为纯函数,返回值为redux state

ts类型:

(1)、action 
// store/root/action.ts
export default class Actions {
  static NORMAL = "NORMAL";
  static getNormal() {
    return {
      type: Actions.NORMAL
    };
  }
}


(2)、dispatch
// store/root/middleware.ts
import {Dispatch} from "redux";
import Actions from "./actions";
import ReduxState from '@store/type';

type GetNormal = ReturnType<typeof Actions.getNormal>;
type GetState = () => ReduxState;
export default class Middleware {
  // Signin Functions Starts
  static setNormal() {
    return (dispatch: Dispatch<GetNormal>, getState: GetState ) => {
      dispatch(Actions.getNormal());
    };
  }
}


(3)、reducers
// store/root/reducers.ts
import {AnyAction} from 'redux';
import Actions from "./actions";
import RootState from './type';

const INITIAL_STATE: RootState = {
  title: "来自redux的默认标题",
  isNormal: false,
  successful: false,
  failed: false,
};
const root = (state: RootState = INITIAL_STATE, action: AnyAction) => {
  switch (action.type) {
    case Actions.NORMAL:
      return {
        ...INITIAL_STATE,
        isNormal: true
      };
    default:
      return state;
  }
};
export default root;


// store/root/type.ts
export default interface RootState {
  title: string;
  isNormal: boolean;
  successful: boolean;
  failed: boolean;
}


// store/reducers .ts
import {combineReducers} from 'redux';
import root from './root/reducers';
const reducers = combineReducers({
  root: root,
});
export default reducers;


// store/type.ts
import reducers from './reducers';
type ReduxState = ReturnType<typeof reducers>;
export default ReduxState;

/*
	redux相关文件夹如下
	├── store                                  // redux相关文件夹
    │   ├── root                              // module1
    │        ├──action.ts                     // module1 的action文件
    │        ├──middleware.ts                 // module1 的middleware文件
    │        ├──reducers.ts                   // module1 的reducers文件
    │   ├── reducers.ts                       // combineReducers 文件
	│   ├── type.ts                           // redux所有state类型管理文件
    │   ├── configStore.ts                    // store 配置文件
*/

react-redux:

//部分代码
import Middleware from "@store/root/middleware";
import {bindActionCreators, Dispatch, AnyAction} from "redux";
import ReduxState from '@store/type';
const mapStateToProps = ({root}: ReduxState) => ({
  title: root.title
});
const mapDispatchToProps = (dispatch: Dispatch<AnyAction>) => bindActionCreators({
  setNormal: () => Middleware.setNormal()
}, dispatch);

关键点在于理解redux的几个核心概念

ReturnType 也是ts的内置类型,日常开发会经常使用到

ReturnType<T> -- 获取函数返回值类型。
type T10 = ReturnType<() => string>;  // string
type T11 = ReturnType<(s: string) => void>;  // void