详解Typescript 严格模式有多严格

yizhihongxing

详解Typescript 严格模式有多严格

简介

Typescript 自2.3版本开始引入了“严格模式”(Strict mode),它通过加强类型检查、禁用一些不安全的语法和行为等手段来让代码更规范、更健壮,从而减少意外的运行时错误。

在这篇文章中,我们将详细讲解 Typescript 严格模式的多个方面,并给出一些示例代码来进一步说明各个模式之间的区别。

严格模式开启方式

要开启 Typescript 严格模式,只需要在 tsconfig.json 文件中将 strict 选项设置为 true 即可。

{
  "compilerOptions": {
    "strict": true
  }
}

这个选项会同时开启以下严格模式子选项:

  • noImplicitAny
  • strictNullChecks
  • strictFunctionTypes
  • strictBindCallApply
  • noImplicitThis
  • alwaysStrict

noImplicitAny

如果一个变量的类型没有被显式定义,并且 Typescript 也无法从上下文中推断出其类型,那么它的类型就会被默认设置为 any,这样就没有类型检查的效果了。

举个例子:

function add(a, b) {
  return a + b;
}

add(1, 2); // 3
add('hello', 1); // 'hello1'

这个例子中,add 函数中的参数和返回值都没有明确指定类型,因此它们的类型都被默认设置为 any,这样就可以传入任意类型的参数了,显然这是不规范的。

在开启 noImplicitAny 选项后,编译器会对未显式定义类型的变量、函数参数和返回值进行报错,提示你应该明确它们的类型。

strictNullChecks

在 Javascript 中,变量默认是可以为 nullundefined 的,这常常成为一些难以定义变量类型的问题。

let foo;

console.log(foo.length); // TypeError: Cannot read property 'length' of undefined

在这个例子中,由于 foo 变量没有被初始化,它的值为 undefined,那么当我们尝试对它进行字符串长度的访问时,就会报错。

开启 strictNullChecks 选项后,编译器会在类型检查时对这种行为进行报错,从而让代码更加健壮。

let foo: string | undefined;

console.log(foo.length); // Error: Object is possibly 'undefined'.

在这个例子中,我们将 foo 变量的类型显式设置为 string | undefined,这意味着它可能是字符串类型,也可能是 undefined,这样可以有效地避免了前面的报错。

strictFunctionTypes

函数是 Javascript 中的重要组成部分,Typescript 严格模式中对函数的类型匹配进行了强制验证,防止常见的隐式的类型转换,在开发过程中更容易发现错误。

type AddFn = (a: number, b: number) => number;

const add1: AddFn = (a, b) => a + b;
const add2: AddFn = (a: number, b: number) => `${a}${b}`;

add1(1, 2); // 3
add2(1, 2); // Error: Type '(a: number, b: number) => string' is not assignable to type 'AddFn'.

在这个例子中,我们定义了一个函数类型 AddFn,它接收两个数字类型的参数,并返回一个数字类型的值。但如果我们将一个返回字符串类型的函数赋给 AddFn 类型的变量,编译器就会报错,从而让我们更早地发现这个错误。

strictBindCallApply

在 Javascript 中,bindcallapply 方法能够改变函数的 this 值,有时候也会造成不必要的麻烦。

function foo(this: number) {
  console.log(this);
}

foo(); // TypeError: this is undefined
foo.call('hello'); // TypeError: '"hello"' is not a number.

在这个例子中,我们定义了一个只能在数字上下文中调用的函数 foo,如果它被单独调用,或者尝试在字符串上下文中调用,都会产生不规范的结果。

在开启 strictBindCallApply 选项后,编译器会对这种行为进行报错,从而让代码更加健壮。

function foo(this: number) {
  console.log(this);
}

foo(); // Error: The 'this' context of type 'void' is not assignable to method's 'this' of type 'number'.
foo.call('hello'); // Error: Argument of type 'string' is not assignable to parameter of type 'number'.

在这个例子中,我们在函数定义时声明了它的 this 值类型为 number,这样可以避免它被误用在非数字上下文中。另外,当我们尝试使用 call 方法时,编译器会报错提示参数类型不匹配的问题。

noImplicitThis

在一些 Javascript 中,函数内的 this 值可能是不确定的,这通常发生在事件回调函数、定时器函数等场景中,这个时候编译器可能无法判断函数内部 this 值的类型,使用 this 值时可能会因为类型问题产生错误。

class Button {
  private onButtonClick() {
    console.log(this.text);
  }

  constructor(public text: string) {
    document
      .querySelector('button')
      .addEventListener('click', this.onButtonClick);
  }
}

new Button('Hello'); // undefined

在这个例子中,我们想要将按钮点击事件的回调函数 onButtonClick 绑定到 Button 类的实例上,但实际上这个回调函数并没有被正确地绑定到当前类的实例上,这样就无法访问当前实例的 text 属性,从而导致出错。

在开启 noImplicitThis 选项后,编译器会在这种情况下发出警告,从而提示我们应该先针对 this 值类进行显式声明。

class Button {
  private onButtonClick = () => {
    console.log(this.text); // 这里的 this 就是 Button 类的实例
  };

  constructor(public text: string) {
    document
      .querySelector('button')
      .addEventListener('click', this.onButtonClick);
  }
}

new Button('Hello'); // 'Hello'

在这个例子中,我们将回调函数 onButtonClick 定义为一个箭头函数,并且在箭头函数中访问 this.text 属性,这样就避免了上述的问题。

alwaysStrict

开启 alwaysStrict 选项后,编译器会在生成的 Javascript 代码中插入 "use strict" 指令,这会强制执行 Javascript 严格模式,进一步减少代码中出现的一些不规范行为和错误。

示例代码:

// tsconfig.json
{
  "compilerOptions": {
    "alwaysStrict": true
  }
}

// test.ts
function add(a: number, b: number) {
  return a + b;
}

console.log(add(1, 2));

编译后的 Javascript 代码:

"use strict";
function add(a, b) {
  return a + b;
}
console.log(add(1, 2));

结论

通过对上述几个严格模式进行逐一解释和对比,我们可以看到 Typescript 严格模式在加强类型检查、去除不规范语法和行为、提高静态分析等方面都做了各自的工作,使得开发工作更加规范、高效。在使用 Typescript 进行项目开发时,这些严格模式可以有效地降低错误率,提高代码质量。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解Typescript 严格模式有多严格 - Python技术站

(0)
上一篇 2023年6月10日
下一篇 2023年6月10日

相关文章

  • JS实现的3des+base64加密解密算法完整示例

    JS实现的3DES+Base64加密解密算法完整示例 简介 本文介绍了如何使用JavaScript实现一种加密算法——3DES+Base64,包含完整的示例代码。具体而言,我们将使用3DES算法对明文进行加密,并将加密后的结果使用Base64算法编码,以便于传输。同时,我们也将演示如何使用3DES算法进行解密,以还原出原始的明文。 算法介绍 3DES算法 3…

    JavaScript 2023年5月19日
    00
  • JS 遍历 json 和 JQuery 遍历json操作完整示例

    下面为你详细讲解JS遍历JSON和jQuery遍历JSON操作的完整攻略。 JS 遍历 JSON 1. 遍历JSON方法 遍历JSON有两种方法:for…in 和 Object.keys()。 2. for…in 遍历JSON for…in 循环可以用于遍历 JSON 对象以及数组: const myObj = { name: "Joh…

    JavaScript 2023年5月27日
    00
  • javascript实现的字符串转换成数组操作示例

    当我们需要对一个字符串进行一系列的操作时,将字符串转换成数组将是非常有帮助的。JavaScript中,我们可以使用split()方法来将字符串转换成数组,并可以通过指定分隔符来控制数组的元素。下面,我们将介绍一个完整的JavaScript字符串转换成数组的攻略: 步骤1:使用split()方法将字符串转换成数组 首先,我们可以使用split()方法将一个字符…

    JavaScript 2023年5月27日
    00
  • JavaScript遍历查找数组中最大值与最小值的方法示例

    下面是针对 JavaScript 遍历查找数组中最大值与最小值的方法的详细攻略。 算法原理 以下是查找数组中最大值与最小值的算法原理: 初始化最大值和最小值,将最大值和最小值分别设置为数组的第一个元素的值。 使用循环遍历数组。 在循环时,判断数组中的当前元素是否大于最大值,如果是,则将最大值设为当前元素的值。 在循环时,判断数组中的当前元素是否小于最小值,如…

    JavaScript 2023年5月28日
    00
  • JavaScript 之JS的组成与基本语法

    下面是详细的“JavaScript 之JS的组成与基本语法”攻略: JS的组成与基本语法 JS的组成 在研究JS的基本语法之前,必须了解JavaScript的组成。JavaScript由以下3部分组成: ECMAScript:JavaScript的基础语法部分,包含了核心语言功能和对象。 DOM:Document Object Model,文档对象模型,操作…

    JavaScript 2023年5月17日
    00
  • Javascript基础之数组的使用

    Javascript基础之数组的使用 什么是数组? 数组是Javascript中的一种数据结构,用于存储多个相同类型的数据。一个数组可以包含任意数量的元素,且这些元素可以是数字、字符串、对象、甚至另一个数组。 如何声明一个数组? 声明一个数组的语法是 [],可以选择性地在中括号内包含多个元素。例如: var fruits = [‘apple’, ‘banan…

    JavaScript 2023年5月28日
    00
  • 前端编码规范(3)JavaScript 开发规范

    前端编码规范对于一个团队而言是非常重要的,它有助于提高代码的可阅读性、可维护性,并能够帮助团队成员之间保持协同配合。本文主要讲解 JavaScript 开发规范,下面将详细介绍该规范的内容。 1. 变量与常量命名规范 在 JavaScript 开发中,变量与常量命名应当遵循以下规范: 变量和常量名应该基于语义而非单词缩写 全局变量使用 全大写常量 的方式定义…

    JavaScript 2023年5月18日
    00
  • 详解JS对象封装的常用方式

    关于JS对象封装的常用方式,我可以提供以下完整攻略。 一、什么是对象封装 对象封装是一种将数据和相应的方法捆绑在一起的面向对象编程技术,以实现数据封装和信息隐藏的目的,有助于提高代码的可读性、可维护性、可扩展性和代码复用性。 在JavaScript中,对象封装可以通过创建对象或构造函数等方式来实现。常用编写对象封装的方式有:对象字面量、构造函数、原型和ES6…

    JavaScript 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部