React TSLint中常见的问题及处理方法

本文中很多地方会用ts表示typescript。本文主要针对刚使用typescript和tslint的同学,新手使用TSLint规则校验typescript代码时,总会碰到一些TSLint的错误提示,花费较多的时间和精力去解决这些错误信息,本篇文章将列出本人在项目开发中使用TSLint碰到的问题,及解决方案。TSLint是可配置的,如果项目中引用了TSLint,会有一个tslint.json的配置文件,可以通过其中的配置项去选择需要校验的规则,不知道如何配置的同学可以访问: [link]: palantir.github.io/tslint/rule… 网上也有很多关于配置的文章。 声明:本文中TSLint的提示信息为本次项目中tslint.json所配置的校验规则。

声明、导入

当我们在使用React + js 时,声明一个变量、声明一个函数、导入一个模块等等,声明或导入后没有使用,也不会报错。程序也能正常运行。但在ts中声明了就需要去使用,不然就会。。。

举个例子,本文会重复使用这个例子作为参考

这里是第一个例子,本人用截图的方式把代码和错误提示展示出来,后面的错误提示或者运行时的错误信息,会在例子的下面标注出来,会在例子的下面标注出来,会在例子的下面标注出来。好了,重要的事情说三遍。

从上图中可以看出,错误提示很明显,IConfig声明了但没有引用。声明变量、声明函数、导入模块等,声明或导入后没有引用就会有上图这样的错误提示,或者运行时会有大概一下几种错误提示:

  1. '***' is declared but its value is never read.
  2. 'IConfig' is declared but never used.
  3. All imports in import declaration are unused.

总之碰到这些类型错误的时候还是很好解决的,我们去使用它不就得了。还是上面的这个例子,作为第一个解决方案,我们也使用截图。。。

这时就没有错误提示啦,是不是很开心。。。故事当然不会这么快就结束。运行时出现了这个错误:An empty interface is equivalent to {}.因为我们在tslint.json中设置了"no-empty-interface":true,我们需要这样做:

import React from 'react';
interface IConfig {
  orgName: 'bwa'
}
class Test extends React.Component<IConfig> {
  public render() {
    return (
      <div />
    );
  }
}
export default Test;
复制代码

声明的错误类型暂时到这里到这里,上面的代码已经可以正常运行。

tslint这样处理的优点

  1. 避免了不必要的变量声明,及减少了从未使用到的僵尸代码。
  2. 避免了不必要的导入模块、函数,使整个项目更加轻量级。
  3. 可读性更高。

导入一个接口或一个方法时tslint的提示

现在我们的编辑器都相当的智能,本人使用的是VSCode,把鼠标移到方法上面就会有他的使用方式。

例子:

import React from 'react';
import { RouteComponentProps, withRouter } from 'react-router';
interface IConfig {
  orgName: 'bwa';
}
class Test extends React.Component<IConfig & RouteComponentProps<>> {
  public render() {
    return (
      <div />
    );
  }
}
export default Test;
复制代码

上面的代码在使用RouteComponentProps这个路由接口时tslint会有:Generic type 'RouteComponentProps<P, C>' requires between 1 and 2 type arguments. RouteComponentProps需要1~2个参数。我们只需要改动:

class Test extends React.Component<IConfig | RouteComponentProps<{name: gtx}>> {}
复制代码

{name: gtx}里的name表示路由上的'/files/data/:name'。

鼠标放在withRouter上时,提示他是一个函数,它继承了RouteComponentProps接口,它有一个参数,并且这个参数的类型是组件类型,这个方法返回的是一个组件,这个组件拥有了RouteComponentProps里面定义的参数。

用法:

export default withRouterTest(Test);
复制代码

tslint这样处理的优点

  1. tslint较为直观的提示我们接口、方法应该怎样使用,需要的参数类型。
  2. 不需要编译就能知道错误的准确位置,更正方法。

对象的键排序,这里使用的是按字母的顺序排序

class Test extends React.Component<IConfig & RouteComponentProps<{ name: 'gtx' }>> {
  public state: {
    age: number;
    sex: string;
  } = {
      sex: '男',
      age: 18,
    };
  public render() {
    return (
      <div />
    );
  }
}
复制代码

这是我们编译时,浏览器会提示:The key 'age' is not sorted alphabetically 需要按字母顺序排序。关于键需要按字母顺序排序之类的问题,很好理解我们就不多说了。

{
  age: 18,
  sex: '男',
};
复制代码

当两个对象的键比较多且要求相等,我们有时会落下其中的某个键,如果不是按一定规则排序的话就会非常难寻找。

tslint这样处理的优点

  1. 容易比对出是什么地方落下的某个键,(小技巧:按字母排序的话,比对同一个字母开头的键的开始行与结束行?);

类型问题

import React from 'react';
import { RouteComponentProps, withRouter } from 'react-router';
interface IConfig {
  orgName: 'bwa';
}
interface IData {
  data: IConfig[]
};
class Test extends React.Component<IConfig & RouteComponentProps<{ name: 'gtx' }>> {
  public state: {
    age: number;
    sex: string;
    results: IData;
  } = {
      age: 18,
      sex: '男',
    };
  public render() {
    return (
      <div />
    );
  }
}
export default withRouter(Test);
复制代码

这时我们的state会报:Type '{ sex: string; age: number; }' is not assignable to type '{ age: number; sex: string; results: IData; }'. Property 'results' is missing in type '{ sex: string; age: number; }'. 类型XXX不能赋给类型XXX ,仔细看里面的提示理会发现没有给state里面的键results赋值。好吧,根据提示我们来给他赋值

 public state: {
  age: number;
  results: IData;
  sex: string;
} = {
    age: 18,
    results: {
      data: []
    },
    sex: '男',
  };
复制代码

看到这里你可能会说如果键的类型有多种呐,并且tslint.json中设置了no-any,那我怎么声明键的类型呐?嗯,往下看

  public state: {
  age: number;
  hobby: number | string | string[] | IData[] | IData;
  results: IData;
  sex: string;

} = {
    age: 18,
    hobby: 1 || '男' || {data: 'data'},
    results: {
      data: []
    },
    sex: '男',
  };
复制代码

1 || '男' || {data: 'data'} 中任何一种都可以赋值给hobby,只写其中一个也是可以的。

tslint这样处理的优点

  1. 当我们指定了类型,它就只能是这种类型,这样的定义,强类型的变量、参数写出来的代码更加的严谨,后期的维护更加的方便。
  2. 可读性更高。

声明变量与组件的名字一样或与引入组件的名字一样时

class Test extends React.Component {
 public child = () => {
   const Test = <hr />;
   return (
     Test
   );
 }
 public render() {
   return (
     <div>
       {this.child()}
     </div>
   );
 }
}
复制代码

错误提示: Shadowed name: 'Test',此时我们只需要重新声明变量的名字如const Test -->const hr;

tslint这样处理的优点

  1. 避免了作用域的混淆(声明变量与组件的名字一样或与引入组件的名字一样,调用时很容易出错,往往这样的错误让人很头疼)。
  2. 对开发者更加的友好(不用凭记忆去衡量模块命名是否已占用了这个变量名)。

console打印信息

在js中我们常用console打印一些信息在控制台,在tslin中很多时候会禁用掉console

tslint.json---> no-console: true; 这时你使用console.log的话就会:Calls to 'console.log' are not allowed.

如何解决呢?

import debug from 'debug';
const log = debug('Component:Test');
复制代码

这时我们需要打印信息时调用log('想打印的内容');同时在chrome浏览器 -->开发者模式 --> Application --> Local Storage 里添加: Key: debug, Value: Component:Test,这时我们就能打印出想打印的内容。

如图

这样做的优点:

  1. 定义了是哪个组件下打印的内容 :Component:Test 这里是Test下的
  2. Local Storage 里设置了需要接收的组件,这样的好处在于,我们在代码里写了log,但不需要去清除,其他电脑访问相同页面时控制台也会很干净,不会打印出这些信息。
  3. 不同组件下的log信息会以不同的颜色区分。

本篇文章暂时就到这里。

原文链接:tech.gtxlab.com/tslint-code…


作者信息:宁文飞,人和未来大数据前端工程师

转载于:https://juejin.im/post/5ca56f42f265da30d47b1739

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值