当前位置: 首页 > news >正文

挑战Typescript项目中的strict编译模式

概述

将手上的angular项目升级最新版本,并将typescript也升级到最新版本,结果vs code中打开tsconfig.json有个红色的警告,说是添加strict选项,以减少类型错误。作为一个有强迫症的程序员,决定一试,用这个选项来提高代码的优雅度。

加入strict选项后,运行ng build之后,原本运行正常的程序,突然之间出现了一堆错误。

后边对修正的内容进行一一记录。

变量参数

用了strict参数后,所有参数变量都要指定类型。否则报这样的错误:

error TS7006: Parameter 'name' implicitly has an 'any' type.

 本来any是没问题的,但现在必须显示指定。比如一个类方法是这样的:

getDataStore(name, keyExpr, needpage?, aditional?) 

现在就变成,最后一个参数可以直接指定any类型:

getDataStore(name:string, keyExpr:string, needpage?:boolean, aditional?:any)  

 再如下边这个错误:

error TS7005: Variable 'items' implicitly has an 'any[]' type.

const items=[];

......

return items;

 编译器认为这样隐匿any[]类型不行,要显式指出,改成这样就过了:

const items:any[] = [];

……

return items;

 当然有条件的话,能定义相应的接口类型,这样可以更加有利于定位错误。

空值(null)检查

用strict编译选项后,如果上下文不能保证变量不为null,则会报错,比如:

error TS2531: Object is possibly 'null'.

24     const modes = localStorage.getItem('modes').split(',');

 这里从本地存储中获取一个值。虽然业务上保证这地方不可能为null,但从编译器的角度来讲,只要不是直接定义赋值的地方都有可能为null,所以报了这个错。实际上就是要求split()方法前的对象必须有效。

那这里修改思路有两个,一是给定默认值,另一个如果为null则不调用split(),这里采用后者,代码自改成如下:

 const str = localStorage.getItem('modes');
    if (str) {
      const modes = str.split(',');
}

编译通过。

再比如以下错误:

error TS2322: Type 'null' is not assignable to type '{ email: string; userName: string; }'.

394     this._user = null;

 原因是_user在定义的时候,显式给字类型,而null并不是从给定类型继承的,所以不能赋值,这跟java,c#之类的编程语言不同,不能直接给null,此时还是用any大法,在定义的时候指定any类型:

private _user: any = { email: '', userName: '' };

 还有属性为空的情况:

error TS2531: Object is possibly 'null'.

16     let p=route.routeConfig.path??'';

 改成这样:

 let p=route.routeConfig?.path??'';

 再来一个null问题:

Error: src/app/shared/components/side-navigation-menu/side-navigation-menu.component.ts:85:7 - error TS2531: Object is possibly 'null'.

85       this.menu.instance.collapseAll();

 代码修改为:

this.menu?.instance?.collapseAll();

编译通过。

 类型匹配

当一个值可能为null的时候,会引起类型匹配的异常。比如下边这个错误,它是将null当成一种类型,因为userId有可能为null,所以出现了因类型不匹配而不能赋值的错误。考虑到此处null没有什么实际意义,可以强制为string类型。

Argument of type 'string | null' is not assignable to parameter of type 'string | Blob'.
  Type 'null' is not assignable to type 'string | Blob'.

353       formData.append('userId', this.userId);

代码修改如下:

formData.append('userId', this.userId + '');

 编译通过。

看一个参数类型不一致的情况:

error TS2345: Argument of type 'number' is not assignable to parameter of type 'never'.

43     this.viewBox.push(width);

 这里把width改any类型即可:

let width:any=....;

属性初始化

类属性如果没做初始化,也会编译报错:

error TS2564: Property 'user' has no initializer and is not definitely assigned in the constructor. 

21   user: { email: string, userName: string };

这里给个初始值:

@Input()
  user: { email: string; userName: string } = { email: '', userName: '' };

 感觉这地方有点多余,本来可以进行空值判断的,这么一改变成默认值判断了。

不能初始化null的错误:

Error: src/app/shared/components/side-navigation-menu/side-navigation-menu.component.ts:39:3 - error TS2322: Type 'null' is not assignable to type 'DxTreeViewComponent'.      

39   menu: DxTreeViewComponent = null;

 因为null是个独立的类型,如果初始化需要事先设为null,那么要给变量指定null类型:

  @ViewChild('mapdiv', { static: true }) mapdiv: ElementRef | any= {};

再看一个 never类型的错误:

error TS2339: Property 'name' does not exist on type 'never'.

72     return t?.name;

原来代码是这样的:

const t = this.usingVehicleTypes.find((el) => el.id === id);
    return t?.name;

 大概是find()返回值不符合Array所定义的返回类型,因此造成类型不匹配的错误,修改如下:

const t:any = this.usingVehicleTypes.find((el:any) => el.id === id);
    return t?.name;

 暂时先去除类型检查,编译通过。

总结

这个项目开始时,是当成js来写了,充分使用了js的动态特性,所以大部分地方都没标注变量类型,在strict选项下,给变量加类型标注成了最主要的任务。由于json对象,基本从服务器端获得的,客户端并未定义相应的数据类型,有时加类型标注成了困难,好在有个any对象,暂时全部标注成any。总之,强类型的编程语言有利于代码的维护,但ts建立js之上的,有时不知不觉会去使用js的特性,而ts的强类型特性就会带来困扰,所以在用ts的时候,我们要注意这当中的变化。

相关文章:

  • 西门子1200PLC中OB,FC,FB,DB
  • 微软宣布 S2C2F 已被 OpenSSF 采用
  • Pipenv使用指南:轻量级虚拟环境管理工具详解
  • 汉字风格迁移篇----CS-GAN:中国书法翻译的跨结构生成对抗网络
  • [安装] 搭建hadoop集群
  • React - setState 更新状态的两种写法
  • pinia 持久化存储
  • A-Level商务例题解析及练习Theory of Maslow Theory of Herzberg
  • Head First设计模式(阅读笔记)-11.组合模式
  • 手把手教你成为荣耀开发者:数据报表使用指引
  • java计算机毕业设计企业人事管理系统源程序+mysql+系统+lw文档+远程调试
  • HDFS的概念及shell操作
  • Spring Web 应用程序中的 Flash 属性指南
  • 虚拟机共享物理机网路的NAT连接方法
  • Netty入门——基于NIO实现机器客服案例
  • Maven项目管理工具
  • 探索可观测性:AIOps中的时序数据应用
  • RISCV:cv_regress
  • 计算机毕业设计Java校园管理系统(系统+源码+mysql数据库+lw文档)
  • (附源码)Springboot中北创新创业官网 毕业设计 271443
  • 电加热油锅炉工作原理_电加热导油
  • 大型电蒸汽锅炉_工业电阻炉
  • 燃气蒸汽锅炉的分类_大连生物质蒸汽锅炉
  • 天津市维修锅炉_锅炉汽化处理方法
  • 蒸汽汽锅炉厂家_延安锅炉厂家
  • 山西热水锅炉厂家_酒店热水 锅炉
  • 蒸汽锅炉生产厂家_燃油蒸汽发生器
  • 燃煤锅炉烧热水_张家口 淘汰取缔燃煤锅炉
  • 生物质锅炉_炉
  • 锅炉天然气_天燃气热风炉