详解Typescript 严格模式有多严格

详解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日

相关文章

  • 记录-Symbol学习笔记

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 Symbol是JavaScript中的原始数据类型之一,它表示一个唯一的、不可变的值,通常用作对象属性的键值。由于Symbol值是唯一的,因此可以防止对象属性被意外地覆盖或修改。以下是Symbol的方法和属性整理: 属性 Symbol.length Symbol构造函数的length属性值为0。 …

    JavaScript 2023年5月5日
    00
  • JAVA使用Gson解析json数据实例解析

    简介 JSON是一种轻量级的数据交换格式,很多时候我们需要在Java中使用JSON格式进行数据的传递或解析,在Java中使用Gson库可以方便地实现JSON的解析和生成。 Gson是Google提供的Java解析JSON的库,它可以将JSON字符串转化为Java对象,也可以将Java对象转化为JSON字符串。 基本概念 在使用Gson进行JSON解析时,需要…

    JavaScript 2023年6月11日
    00
  • JavaScript几种形式的树结构菜单

    下面为大家详细讲解 JavaScript 几种形式的树结构菜单的完整攻略。 什么是树结构菜单 树结构菜单是一种常见的用于网站导航或者分类展示的组件。树结构菜单的特点是可以展开、收起某一层级的菜单,同时高亮显示当前选中的菜单项。在前端开发中,我们可以使用 JavaScript 来实现这种树状结构的菜单。 JavaScript 实现树结构菜单的基本思路 在使用 …

    JavaScript 2023年6月11日
    00
  • 结构型-代理模式

    定义   代理是一个中间者的角色,如生活中的中介,出于种种考虑/限制,一个对象不能直接访问另一个对象,需要一个第三者(中间代理)牵线搭桥从而间接达到访问目的,这样的就是代理模式。 es6 中的代理  es6 的 proxy 就是上面说的代理模式的实现,es6 帮我们在语法层面提供了这个新的api,让我们可以很轻松的就使用了代理模式。 const p = ne…

    JavaScript 2023年4月18日
    00
  • JavaScript返回当前会话cookie全部键值对照的方法

    要返回当前会话中cookie的全部键值对照,可以使用JavaScript的Document.cookie属性和一些字符串处理方法。下面是完整的攻略步骤: 步骤一:获取当前会话的全部cookie字符串 首先,使用Document.cookie属性获取当前页面的全部cookie字符串。该属性的返回值是一个字符串,它包含当前文档中所有cookie的键值对,使用分号…

    JavaScript 2023年6月11日
    00
  • javascript 伪数组实现方法

    下面是关于Javascript伪数组实现方法的详细攻略。 什么是Javascript伪数组? Javascript中的伪数组是一个类数组对象(array-like object),它具有一个length属性和一些从0开始的数字索引,但是它没有数组对象的方法,比如push、pop、splice等。它一般用来存储一系列数据,但没有需要数组方法的操作时,就可以使用…

    JavaScript 2023年5月27日
    00
  • vue使用axios实现excel文件下载的功能

    下面是使用Vue和Axios实现Excel文件下载的攻略,过程中将会包含两条示例说明。 准备工作 安装依赖:npm install –save axios file-saver xlsx 其中,axios 是我们将用来与后端交互的网络请求库;file-saver 是将文件保存到本地的库;xlsx 将Excel文件转换为二进制格式。 在 main.js 中导…

    JavaScript 2023年6月11日
    00
  • java NIO 详解

    Java NIO 详解 Java NIO(New IO)是一种基于缓冲区、非阻塞IO的API集,主要用于替代传统的Java IO API。它可以更高效地处理IO数据,具有更好的扩展性和灵活性,尤其适用于处理大量连接和请求的场景。 在本文中,我们将从以下几个方面对Java NIO进行详细讲解: 缓冲区(Buffer)及其操作 通道(Channel)及其操作 选…

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