欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

了解 TypeScript:一种强大的JavaScript超集

最编程 2024-07-27 20:19:42
...

这是一个系列文章,一共会有三篇:

  1. [本篇] 认识 TypeScript - 简单描述 TypeScript 的定位、特点。

  2. TypeScript 语法学习 - 比较文档化的讲述 TypeScript 的使用方式。

  3. TypeScript 工程使用 - 讲述如何在工程 —— 包括 Node.js 工程、React 工程 —— 中应用 TypeScript。

最近几个月有幸体验了 TypeScript,它对大型软件 —— 大型 JavaScript 软件 —— 开发来说真是一把利刃。就像我斜后方那个男人一样,写了 TypeScript 就不想再写 JavaScript 了 —— 真乃取其精华去其糟粕啊!

没想到我一个 Linux 的老用户 Copyleft 的忠实拥护者,也会像今天这样喜欢用 M$ 出的东西,17 岁到 19 岁的我一定会鄙视死现在的我。

背景认识

TypeScript 是微软开发一款开源的编程语言,本质上是向 JavaScript 增加静态类型系统。它是 JavaScript 的超集,所有现有的 JavaScript 都可以不加改变就在其中使用。它是为大型软件开发而设计的,它最终编译产生 JavaScript,所以可以运行在浏览器、Node.js 等等的运行时环境。

什么是类型系统

下面是摘自 TypesAndProgrammingLanguages 中的定义:

A type system is a tractable syntactic method for proving the absence of certain program behaviors by classifying phrases according to the kinds of values they compute.

第一个重点是 Provingthe absence of certain program behaviors,所以我们亦可将类型检查器看做一个程序推理工具,可以静态的证明程序成立。

另一个重点是 Classifyingphrases according to the kinds of values they compute,对词语(比如变量)的值的性质进行分类,比如说 TypeScript 中的 InterfaceClass 等能力。

静态类型系统是什么

增加 静态这个定语,是为了和运行时的类型检查机制加以区分,强调 静态类型系统是在编译时进行类型分析。

JavaScript 不是一个静态编译语言,不存在编译这一步骤。但从 程序推理工具 的角度来看,JavaScript 的配套中还是有不少的,比如 ESLint 这个不完备的 程序推理工具

静态类型系统与 Lint 工具的关系

我们先看 ESLint 的定义:

Code linting is a type of static analysis that is frequently used to find problematic patterns or code that doesn’t adhere to certain style guidelines.

区别一

同样强调 StaticAnalysis,不过更强调 CertainStyleGuidelinesLint工具是一种团队协作时的风格规范工具。

区别二

静态类型类型分析Lint工具 的区别在于 Lint工具 没有 Classifyingphrases according to the kinds of values they compute

Lint工具无法基于类型对程序进行静态分析,但两者都有基于 CFG(控制流图,ControlFlowGraph对程序进行分析的能力。比如 TypeScript 的控制流分析、 ESLintcomplexity (当你想写个比较复杂的迭代算法时,这个规则就是个渣) 规则等。

TypeScript 和 JavaScript 的关系

和一些基于 JavaScript 的激进语言不同(比如 CoffeeScript),TypeScript 的语法设计首先考虑的就是兼容 JavaScript,或者说对 JavaScript 的语法做扩展。基本上是在 JavaScript 的基础之上增加了一些类型标记语法,以实现静态类型分析。把这些类型标注语法去掉之后,仍是一个标准的 JavaScript 语言。

TypeScript 同样也在做一些新语法编译到老语法的事情(就像 Babel 做的), 基本实现常用的 EcmaScriptStage1 以上的语法特性。

类型系统的益处

侦测错误

静态类型分析首要优点就是能尽早的发现逻辑错误,而不是上线之后才发现。比如我们在 JavaScript 中经常发生的问题,函数返回值含混。在开发过程中坚信一个函数返回字符串,但到了线上接受了真实数据却返回了 undefined。看似一个简单错误,却可能给公司造成数以万计的损失。

看个例子。

  
    
  
  
  
  1. // 通过分数获取图标

  2. function getRankIcon(score) {

  3.  if(score >= 100) {

  4.    return '';

  5.  } else if(score >= 500) {

  6.    return '';

  7.  } else if(score >= 1500) {

  8.    return '';

  9.  }

  10. }

  11. const icon = getRankIcon(5);

  12. const iconArray = icon.split();

脆弱的 JS 啊,执行一下,Ops!

  
    
  
  
  
  1. > node taste.js

  2. TypeError: Cannot read property 'split' of undefined

相同的逻辑我们用 tsc 编译一下(甚至不需要增加任何的类型标注)。直接静态分析出来程序有一个 undefined

  
    
  
  
  
  1. > tsc --strictNullChecks taste.ts

  2. x.ts(11,19): error TS2532: Object is possibly 'undefined'.

另一个重要的用处是作为维护工具(重构辅助工具),假如我们有一个很通用的函数,在工程里用的到处都是,有一天我们要在这个函数最前面增加一个参数。TypeScript 中你只需要改那个函数就好了,然后再执行静态类型分析,所有和这个函数参数不匹配的地方都会提示出来。但是,在 JavaScript 里,这个改动很有可能被忽略或者漏掉,打包也不会报错,然后发布后线上就挂了……

抽象

类型系统的另一个优点是强化规范编程,TypeScript 提供了简便的方式定义接口。这一点在大型软件开发时尤为重要,一个系统模块可以抽象的看做一个 TypeScript 定义的接口。

用带清晰接口的模块来结构化大型系统,这是一种更为抽象的设计形式。接口设计(讨论)与最终实现方式无关,对接口思考得越抽象越有利。

换句话说就是让设计脱离实现,最终体现出一种 IDL(接口定义语言,InterfaceDefineLanguage,让程序设计回归本质。

看个例子。

  
    
  
  
  
  1. interface Avatar {

  2.  cdnUrl: string; // 用户头像在 CDN 上的地址

  3.  filePath: string; // 用户头像在对象存储上的路径

  4.  fileSize

    上一篇: Spring Boot 中 GenericApplicationListener 事件处理机制详解与应用指南

    下一篇: Java泛型详解:自定义泛型的extends和super用法