在项目中添加类型注解是代码结构文档化非常棒的方式,它提供了一种为传递的数据注明结构的方式。
添加数据类型,可以让我们复盘正在编写的代码,并思考是否能创建更清晰的代码结构以获得更高的代码质量。
添加数据类型,也让我们的代码更利于理解,因为我们不需要深入研究项目就可以了解数据的结构,它消除了很多认知上的复杂性。
配置tsconfig{ "compilerOptions": { "target": "es5", // 指定ECMAscript目标版本 "module": "commonjs", // 指定模块代码生成 "moduleResolution": "node", // 使用Node.js风格解析模块 "jsx": "react", // 支持在.tsx文件中使用jsx "declaration": true, // 生成相应的.d.ts文件 "rootDir": "src", // 指定源文件中的根文件夹 "sourceMap": false, // 是否生成相应的.map文件 "noUnusedLocals": true, // 是否报告未使用的局部变量的错误 "noUnusedParameters": false, // 是否报告未使用参数的错误 "noImplicitReturns": true, // 是否报告隐式返回的错误 "noImplicitAny": false, // 是否允许隐式any类型 "noFallthroughCasesInSwitch": true, // 是否报告switch语句中不可命中情况的错误 "resolveJsonModule": true, // 支持以.json扩展名导入的模块 "outDir": "lib", // 指定输出文件夹 "baseUrl": "./", // 指定用于解析非相对模块名的基本目录 src/xx/xxx "lib": [ "esNext", "dom", ], // 要包含在编译中的库文件列表 }, "include": [ "src*" ], // 指定与要包含在编译中的文件列表}
.eslintrc.js
{ "extends": "@ali/eslint-config-yd", "parser": "@typescript-eslint/parser", "rules": { "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx", ".tsx"] }], "no-use-before-define": "off", "no-unused-vars": "off", "key-spacing": [2, { "beforecolon": false, "aftercolon": true }] }}
package.json
{ "name": "@alife/yd-sddp-lib-types", "version": "1.0.6", "main": "index.js", "types": "lib/types/index.d.ts", "files": [ "lib*.d.ts" ], "devDependencies": { "@types/react": "^18.0.9", "@types/react-dom": "^18.0.3", "@typescript-eslint/parser": "^5.22.0", "eslint": "^6.2.2", "typescript": "^4.6.4", }}
组件是React核心概念之一,有类组件和函数组件,建议使用函数组件进行开发
// 函数组件type DomainTreeProps = { onChange : => any; refreshDomainTreeCount : number; openEditModel : boolean;}// 写法1const DomainTree: React.FC<DomainTreeProps> = => { const { onChange, refreshDomainTreeCount, openEditModel } = props; return ;};// 写法2const DomainTree = => { const { onChange, refreshDomainTreeCount, openEditModel } = props; return ;};export default DomainTree;// 类组件type DomainTreeState = { expand : boolean;}class DomainTree extends React.Component<DomainTreeProps, DomainTreeState> { public state = { expand: false }; render { const { onChange } = this.props; return <p>{this.state.expand}</p>; }}export default DomainTree;
在这个「DomainTree」组件中指定了「DomainTreeProps」也就意味着这个组件只接收相应的类型,我们可以给「DomainTreeProps」中的每个属性添加相应的注释(使用「」方式,这样hover对应属性会有相关注释),以便其他同学更快速的了解上下文,我们还可以通过「 」来表示哪些参数是可选项。
HooksTypescript具备强大的类型推断能力,这让我们在使用hooks开发时也能得心应手。
// 类型系统会自动推断出 count是number类型// setCount是个允许接受number类型或者函数类型的函数 例如:setCount 或 setCount => count++)const [count, setCount] = React.useState;
Typescript根据useState
的参数推断类型,这让我们在实际开发中可以减少很多没必要的类型添加。
但是在有些情况下,我们也可以指定具体的类型。
type SelectStateType = 0 | 1 | 2;const [selectState, setSelectState] = React.useState
指定「selectState」类型是「SelectStateType」,使「setSelectState」只能输入「0,1,2」,有效保障代码逻辑的严谨性。
第三方库类型问题组件不存在问题这时可以使用 「@ts-ignore」忽略类型检查。
// @ts-ignore
「setArchive」根据类型推断只支持number
类型,「UI.Radio.Group」提供的onChange方法返回的val是string | number | boolean
类型,针对这种问题可以使用 as number
断定val为number
类型。
const [archive, setArchive] = React.useState;
在ts项目中,直接给新增的全局变量赋值会报错,会提示window上没有属性xxx,我们可以通过继承Window的属性新增全局变量。
declare global { interface Window { MICRO_APP: React.FC; }}window.MICRO_APP = => ;
函数组件实际应用
全域数据 {rootDomainInfo .totalCount || 0}import { generateTreeData, onDrop } from './helper';import AddOrModifyTree from './AddOrModifyTree';import DeleteTree from './DeleteTree';import './index.scss';import useDescribeDomains from './data';export type DomainInfo = { id: number; name: string; description: string; adminNames: string; authed: boolean | number; aliUid: string; domainLevel: number; domainType: number; instanceIds: string; parentDomainId: number; sort: number; totalCount: number;}type AddTreePanelState = { visible : boolean; record : DomainInfo; type : 1 | 2 | 3; action : 'add' | 'modify'}type DeleteTreePanelState = { visible : boolean; record : DomainInfo;}type SelectedType = 0 | 1 | 2;export interface DomainTreeProps { onChange : => any; refreshDomainTreeCount : number; openEditModel : boolean;}const DomainTree: React.FC
自定义数据域
{openEditModel &&nClick={ => updateCurrentDomainInfo}>
默认数据域
{defaultDomainInfo .totalCount || 0}
{AddTreePanelInfo.visible && setAddTreePanelInfo} refreshDomainTree={refreshDomainTree} />} {DeleteTreePanelInfo.visible &&免责声明:本平台仅供信息发布交流之途,请谨慎判断信息真伪。如遇虚假诈骗信息,请立即举报
举报