关于react项目静态类型检查方案

这篇文章主要介绍了关于react项目静态类型检查方案,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下

为什么需要引入类型检查

JS作为一个弱类型语言,具有很大的灵活性,但是它的优点也是它的缺点,它很容易让我们忽视一些隐晦的逻辑,语法错误或数据类型错误,在编译期甚至运行时看上去都不会报错,但是可能会发生各种各样奇怪的和难以解决的bug。

function getPrice(x) {  return x * 10;}getPrice('a23') // NaN

登录后复制

function getDefaultValue (key, emphasis) {    let ret;    if (key === 'name') {      ret = 'GuangWong';    } else if(key=== 'gender') {      ret = 'Man';    }else if(key ==='age'){      ret = 18;    } else {       throw new Error('Unkown key ');    }    if (emphasis) {      ret = ret.toUpperCase();    }    return ret;  }    getDefaultValue('name'); // GuangWong  getDefaultValue('gender', true) // MAN  getDefaultValue('age', true)

登录后复制

这是一个简单的函数,第一个参数 key 用来获得一个默认值。第二参数 emphasis 为了某些场景下要大写强调,只需要传入 true 即可自动将结果转成大写。

但是如果不小心将 age 的值写成了数字字面量,如果我调用 getDefaultValue(‘age’, true) 就会在运行时报错。这个有可能是业务上线了之后才发生,直接导致业务不可用

除此以外,在工作中,我们也经常遇到过对象上的一个属性在n个模块之间传递之后变成了 undefined。以上是代码健壮性的问题,工作中比较头疼的另外一个问题是协作性问题:如何让一个别人提供的方法产出一个一目了然的文档?因为一个项目总会涉及到多人协作:同学 A 编写了函数 a(),而 同学 B 在调用函数 a() 的时候得一直撸着 API 文档才能知道 a() 需要什么参数,会返回什么参数。

而 同学 A 后续又改动了函数 a(),但是却忘记了更新文档,这时候新接手项目的 同学 C 看着 API 文档和函数 a() 一脸懵逼,问题浮出水面:团队协作中,提供的接口如何描述自身?

这其中涉及到的问题有:

1.接口如何描述自己的参数和返回值?
2.接口参数和返回值在无数需求迭代中改变了多次,而这个 API 对应的文档该如3.何更新?
4.数据格式如何描述?

为了解决上述诸多痛点,我们需要引入类型检查机制,所谓类型检查,就是在编译期尽早发现(由类型错误引起的)bug,又不影响代码运行(不需要运行时动态检查类型),使编写js具有和编写Java等强类型语言相近的体验,它可以:

使得大型项目可维护

提高效率,错误在编写代码时报错,而非编译阶段

增强代码的可读性,可以做到代码即文档

增强设计

采用Flow

Facebook出品的JavaScript静态类型检查工具,它可以部分引入,不需要完全重构整个项目,所以对于一个已有一定规模的项目来说,迁移成本更小,也更加可行

flow使用学习成本也相对比较低

全局安装flow命令行工具

npm install -g flow-bin

登录后复制

在项目根目录,创建.flowconfig文件

安装babel插件

npm install --save-dev babel-plugin-transform-flow-strip-types

登录后复制

在.babelrc文件中添加插件

{  "presets": [ "es2015", "react", "stage-1" ],  "plugins": [        "react-flow-props-to-prop-types"  ]}

登录后复制

安装扩展(⇧⌘X):Flow Language Support

修改VS Code对JavaScript的默认配置

Code -> 首选项 -> 用户设置(⌘,)
搜索:javascript.validate.enable
修改为:”javascript.validate.enable”: false

在项目中使用

在需要静态检查的文件头引入flow,如:

/* @flow */function getPrice(x: number) {  return x * 10;}getPrice('a23') // vscode 工具提示错误

登录后复制

3596645301-5b40e665d2f7b_articlex[1].png

采用typescript

TypeScript 被称是 JavaScript 的超集,是微软公司推出的一种静态代码检查的方案,在 JavaScript 上做了一层封装,封装出 TypeScript 的特性,当然最终代码可以编译为 JavaScript

1.静态类型

let num: number;num = 'likely';    [ts] 不能将类型“"likely"”分配给类型“number”。let num: number

登录后复制

2.函数表达
js写法

export const fetch = function (url, params, user) {  // dosomething  return http(options).then(data => {    return data  }).catch(err => {    return err  })}

登录后复制

以上下是一个 JavaScript 的函数,不看方法内的写法我们完全不知道这个 API 会有哪些坑。

export const fetch = function (url: string | object, params?: any, user?: User): Promise {  // dosomething  return http(options).then(data => {    return data  }).catch(err => {    return err  })}

登录后复制

上述 TypeScript 包含了很多信息,让我们很方便地知道该函数怎么调用

url 可能是 string 或 object 类型

params 是可以不传的,也可以传递任何类型

user 要求是 User 类型的,当然也是可以不传

返回了一个 Promise,Promise 的求值结果可能是 object,也有可能是 Error

3.组件

export interface CouponProps {   coupons: CouponItemModel[]; }export interface couponState {    coupons: CouponItemModel[],    page: number,    size: number,    state: number,  //可用优惠券    hasMore: boolean,    isLoading: boolean,    loadedError: boolean,}class CouponContainer extends React.Component {}

登录后复制

上述组件我们可以清晰地知道一个组件有哪些属性,哪些方法,哪些属性是必传的,哪些是可选的,一目了然,真正做到了代码即文档

关于typescript还有很多其他特点,如类,接口,泛型等,具体可参考官方文档
https://www.typescriptlang.org/

项目迁移typescript

1.node
(1)使用npm安装:npm install -g typescript,当前项目使用了是v2.8.3
(2)2.2 tsconfig.json

{  "compilerOptions": {      "module": "commonjs",      "target": "es5",      "noImplicitAny": true,      "sourceMap": true,      "lib": ["es6", "dom"],      "outDir": "dist",      "baseUrl": ".",      "jsx": "react",      "paths": {          "*": [              "node_modules/*",              "src/types/*"          ]      }  },  "include": [      "src/**/*"  ]}

登录后复制

(3)将.js文件改为.ts
(4)结合 gulp 进行实时编译

var gulp = require('gulp');var pump = require('pump');var webpack = require('webpack');var ts = require('gulp-typescript');var livereload = require('gulp-livereload');var tsProject = ts.createProject("tsconfig.json");gulp.task('compile:tsc:server', function () {  return gulp.src('src/server/**/*.ts')      .pipe(tsProject())      .pipe(gulp.dest('dist/server'));});//将任务同步执行var gulpSequence = require('gulp-sequence');gulp.task('compile', gulpSequence(  'compile:tsc:server',))gulp.task('watch', ['compile'], function() {  livereload.listen();  gulp.watch(['./src/server/**/*.ts'], ['compile:tsc:server']);})

登录后复制

react

可在 webpack 配置文件添加规则

{     test: /.tsx?$/,     enforce: 'pre',    use: [        {            loader: "ts-loader"        }    ] },

登录后复制

3.遇到的问题
遇到的问题

动态地为global添加属性

由于js灵活的风格,我们经常动态地为某一对象添加属性,但是typeScript是编译型语言,基本原则是先定义再使用,所以当我们像下面这么引用

global.testName = '哈哈';

登录后复制

便会出现这样的错误

类型“Global”上不存在属性“testName”

登录后复制

解决方法

(1)将global强制转化为any类型 (global).testName = '哈哈'    (2)扩展原有的对象  global.prototy.testName = '哈哈哈'(3)使用.d.ts文件

登录后复制

declare namespace NodeJS {   export interface Global {    testName: string;  }}

登录后复制

网上很多方法是直接添加一个.d.ts文件即可,但是亲测无效,需要在引用文件引入该文件,如本项目在app.ts文件中引入了

/// 

登录后复制

Flow 与 TypeScript简单对比

1267804671-5b4179e2cc68d_articlex[1].png

总结

Flow或者TypeScript都是静态类型检查的优秀解决方案,能够给有类型检查需求的一定规模的项目带来实际收益。基于现有项目的情况,迁移 TypeScript 时间成本比较大,学习曲线相对陡峭,建议现有项目采用 Flow 方案,对于一些新的项目,可以采用 TypeScript

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

react 官网动画库(react-transition-group)的新写法

react 官网动画库(react-transition-group)的新写法

以上就是关于react项目静态类型检查方案的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2746824.html

(0)
上一篇 2025年3月8日 04:13:25
下一篇 2025年2月19日 07:16:27

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • ES6 Promise中then与catch的返回值的实例

    这篇文章主要介绍了关于es6 promise中then与catch的返回值的实例,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 一.catch为then的语法糖 故then方法与catch方法均会返回一个Promise对象(…

    2025年3月8日 编程技术
    200
  • Vue脚手架的简单使用

    这篇文章主要介绍了关于vue脚手架的简单使用,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 提前申明 注意:自己对vue脚手架的理解和认识,很多东西和理解都是形象上的手法,并不专业和官方 webpack 一种项目构建工具,可…

    2025年3月8日
    200
  • 配置|electron+vue+ts+sqlite的配置方法

    这篇文章主要介绍了关于配置|electron+vue+ts+sqlite的配置方法,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 从编程模型的角度来说,使用声明式语言声明样式和布局,使用功能完备的编程语言编写业务逻辑,算是G…

    编程技术 2025年3月8日
    200
  • Vue iview-admin框架二级菜单改为三级菜单的方法

    这篇文章主要介绍了关于vue iview-admin框架二级菜单改为三级菜单的方法,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 最近在用 iview-admin的Vue后台模板,从git上下载后发现左侧导航栏最多支持到二级…

    2025年3月8日 编程技术
    200
  • 通过Vue属性$route的params传参

    这篇文章主要介绍了关于通过vue属性$route的params传参,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 vue传值 与 vue传参是两块东西 概念图 原理 vue传参的原理主要在于 Vue.$route.param…

    2025年3月8日
    200
  • vscode搭建Typescript+React+Dva的开发环境

    这篇文章主要介绍了关于vscode搭建typescript+react+dva的开发环境,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 [ 作为2018年前端最应该学的技术 ], Typescript 确实惹火, 这两天崩崩…

    2025年3月8日 编程技术
    200
  • JS字符串转数字的方法

    这篇文章主要介绍了关于js字符串转数字的方法,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 String转换为Number有很多种方式,我可以想到的有5种!但总有一些情况让人猝不及防,总结到这里供自己日后查找方便 parse…

    编程技术 2025年3月8日
    200
  • addEventListener中的EventListener的接口对象

    这篇文章主要介绍了关于addeventlistener中的eventlistener接口对象,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 写在最前 遗漏的知识点:addEventListener的第二个参数不光可以传入一个…

    编程技术 2025年3月8日
    200
  • jQuery中css()和attr()方法的区别

    这篇文章主要介绍了关于jquery中css()和attr()方法的区别,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 方法介绍: css(): html代码: 登录后复制登录后复制 jQuery代码: 立即学习“前端免费学习…

    编程技术 2025年3月8日
    200
  • 使用angularJs ng-repeat做表格合并行效果

    这篇文章主要介绍了关于使用angularjs ng-repeat做表格合并行效果,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 描述 使用angularJs做出表格合并的效果 后端返回的数据 [ {“fileName”:”1…

    2025年3月8日
    200

发表回复

登录后才能评论