TypeScript体系调研报告

做者简介:aoto 蚂蚁金服·数据体验技术团队javascript

Q:为何要写这边文章?这篇文章要表达什么?html

A:咱们考虑在SPA应用中使用TS做为开发语言,咱们须要一篇系统性介绍TS自己及周边的文章来论证在项目中使用TS做为开发语言是科学合理的,并且是顺势而为的。前端

导引

  • TS是什么
  • 为何要用TS
  • TS能干点什么
  • 使用TS的成本
  • 社区发展
  • 周边生态
  • 深刻解读TS
  • 接受TS
  • 权衡

TS是什么

TypeScript

TypeScript = Type + Script(标准JS)。咱们从TS的官方网站上就能看到定义:TypeScript is a typed superset of JavaScript that compiles to plain JavaScript。TypeScript是一个编译到纯JS的有类型定义的JS超集。java

为何要用TS

目标:生命周期较长(经常持续几年)的复杂SPA应用,保障开发效率的同时提高代码的可维护性和线上运行时质量。react

  • 从开发效率上看,虽然须要多写一些类型定义代码,但TS在VSCode、WebStorm等IDE下能够作到智能提示,智能感知bug,同时咱们项目经常使用的一些第三方类库框架都有TS类型声明,咱们也能够给那些没有TS类型声明的稳定模块写声明文件,如咱们的前端KOP框架(目前仍是蚂蚁内部框架,类比dva),这在团队协做项目中能够提高总体的开发效率。
  • 从可维护性上看,长期迭代维护的项目开发和维护的成员会有不少,团队成员水平会有差别,而软件具备的特质,长期迭代维护的项目总会遇到可维护性逐渐下降的问题,有了强类型约束和静态检查,以及智能IDE的帮助下,能够下降软件腐化的速度,提高可维护性,且在重构时,强类型和静态类型检查会帮上大忙,甚至有了类型定义,会不经意间增长重构的频率(更安全、放心)。
  • 从线上运行时质量上看,咱们如今的SPA项目的不少bug都是因为一些调用方和被调用方(如组件模块间的协做、接口或函数的调用)的数据格式不匹配引发的,因为TS有编译期的静态检查,让咱们的bug尽量消灭在编译器,加上IDE有智能纠错,编码时就能提早感知bug的存在,咱们的线上运行时质量会更为稳定可控。

一个复杂软件的常规研发流程,大体分为定义问题、需求分析、规划构建、软件架构、详细设计、编码调试、单元测试、集成测试、集成、系统测试、保障维护。构建活动(主要是编码调试)在中大型项目中的工做量占比大于50%。同时,一个中大型项目,bug由构建阶段引发的比例占到50%~75%,对于一个成功的项目来讲,构建活动是必需要作的,并且是工程师更为可控的。【代码大全】webpack

TS适合大规模JavaScript应用,正如他的官方宣传语JavaScript that scales。从如下几点能够看到TS在团队协做、可维护性、易读性、稳定性(编译期提早暴露bug)等方面上有着明显的好处:git

  • 加上了类型系统,对于阅读代码的人和编译器都是友好的。对阅读者来讲,类型定义加上IDE的智能提示,加强了代码的易读型;对于编译器来讲,类型定义可让编译器揪出隐藏的bug。
  • 类型系统+静态分析检查+智能感知/提示,使大规模的应用代码质量更高,运行时bug更少,更方便维护。
  • 有相似VSCode这样配套的IDE支持,方便的查看类型推断和引用关系,能够更方便和安全的进行重构,不再用全局搜索,一个个修改了。
  • 给应用配置、应用状态、先后端接口及各类模块定义类型,整个应用都是一个个的类型定义,使协做更为方便、高效和安全。

TS能干点什么

静态检查

这类问题是ESLint等工具检测不出来的。程序员

低级错误

const peoples = [{
  name: 'tim',
  age: 20
}, {
  name: 'alex',
  age: 22
}];
const sortedPeoples = peoples.sort((a, b) => a.name.localCompare(b.name));
复制代码

执行TS编译命令tsc,检测到错误:github

error TS2339: Property 'localCompare' does not exist on type 'string'.
复制代码

若是是在支持TS的IDE中(VS Code、WebStorm等),则不需等到编译,在IDE中就能够很是明显在localCompare位置提示出错误信息。web

localCompare这种输入手误(或者手滑不当心删除或添加了字符)时有发生,若是没有编译器静态检查,那有可能就是一个字符引起的血案:埋下了一个隐藏的运行时bug。若是在SPA应用中,这个问题须要较长的操做路径才能被发现,一旦用户触发这个地雷,那它就会爆炸:应用直接crash(在没有页面刷新的SPA中问题尤其凸显)。

非空判断

let data = {
  list: null,
  success: true
};
const value = data.list.length;
复制代码

执行tsc编译:

error TS2532: Object is possibly 'null'.
复制代码

data.list.length这行直接引用了data.list的属性,但data.list的数据格式有不是数组的可能性,这种场景在前端处理后端接口返回时常常出现,接口返回的数据层级可能很是深,若是在某一级缺乏了非空判断逻辑,那就意味着埋下了一个不知道何时就会引爆的炸弹。

类型推断

const arr = [];
arr.toUpperCase();

class Cat {
  miao() {}
}

class Dog {
  wang() {}
}
const cat = new Cat();
cat.wang();
复制代码

执行tsc编译:

error TS2339: Property 'toUpperCase' does not exist on type 'any[]'.
error TS2339: Property 'wang' does not exist on type 'Cat'.
复制代码

TS有类型推断,给不一样类型的执行对象调用错误的方法都将被检查出来。

面向对象编程加强

访问权限控制

class Person {
  protected name: string;
  public age: number;
  constructor(name: string) { this.name = name; }
}

class Employee extends Person {
  static someAttr = 1;
  private department: string;

  constructor(name: string, department: string) {
    super(name);
    this.department = department;
  }
}
let howard = new Employee("Howard", "Sales");
console.log(howard.name);
复制代码

执行tsc编译:

error TS2445: Property 'name' is protected and only accessible within class 'Person' and its subclasses.
复制代码

Person中name属性是protected类型,只能在本身类中或者子类中使用。访问权限控制在面向对象编程中颇有用,他能帮忙咱们作到信息隐藏,JS面向对象编程的一个大问题就是没有提供原生支持信息隐藏的方案(不少时候都是经过约定编码方式来作)。信息隐藏有助于更好的管理系统的复杂度,这在软件工程中显得尤其重要。

接口

interface Machine {
  move(): void
}

interface Human {
  run(): void
}

class Base {
}

class Robot extends Base implements Machine, Human {
  run() {
    console.log('run');
  }
  move() {
    console.log('move');
  }
}
复制代码

Robot类能够继承Base类,并实现Machine和Human接口,这种能够组合继承类和实现接口的方式使面向对象编程更为灵活、可扩展性更好。

泛型

class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;
}

let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
复制代码

定义了一个模板类型T,实例化GenericNumber类时能够传入内置类型或者自定义类型。泛型(模板)在传统面向对象编程语言中是很常见的概念了,在代码逻辑是通用模式化的,参数能够是动态类型的场景下比较有用。

类型系统

interface SystemConfig {
  attr1: number;
  attr2: string;
  func1(): string;
}

interface ModuleType {
  data: {
    attr1?: string,
    attr2?: number
  },
  visible: boolean
}

const config: SystemConfig = {
  attr1: 1,
  attr2: 'str',
  func1: () => ''
};

const mod: ModuleType = {
  data: {
    attr1: '1'
  },
  visible: true
};
复制代码

咱们定义了一个系统配置类型SystemConfig和一个模块类型ModuleType,咱们在使用这些类型时就不能随便修改configmod的数据了。每一个被调用方负责本身的对外类型展示,调用者只需关心被调用方的类型,不需关心内部细节,这就是类型约束的好处,这对于多人协做的团队项目很是有帮助。

模块系统加强

namespace N {
  export namespace NN {
    export function a() {
      console.log('N.a');
    }
  }
}

N.NN.a();
复制代码

TS除了支持ES6的模块系统以外,还支持命名空间。这在管理复杂模块的内部时比较有用。

使用TS的成本

学习成本

理论上学习并应用一门新语言是须要很高成本的,但好在TS自己是JS的超集,这也意味着他自己是能够支持现有JS代码的,至少理论上是这样。学习一下类型系统的相关知识和面向对象的基础知识,应该能够hold住TS,成本不会很高。官方文档是最好的学习材料。

应用成本

老项目

对于老项目,因为TS兼容ES规范,因此能够比较方便的升级现有的JS(这里指ES6及以上)代码,逐渐的加类型注解,渐进式加强代码健壮性。迁移过程:

  1. npm全局安装typescript包,并在工程根目录运行tsc --init,自动产生tsconfig.json文件。 默认的3个配置项:更多配置项说明

    • "target":"es5": 编译后代码的ES版本,还有es3,es2105等选项。
    • "module":"commonjs":编译后代码的模块化组织方式,还有amd,umd,es2015等选项。
    • "strict":true:严格校验,包含不能有没意义的any,null校验等选项。
  2. 初始化获得的tsconfig.json无需修改,增长"allowJs": true选项。

  3. 配置webpack配置,增长ts的loader,如awesome-typescript-loader。(若是是基于atool-build来构建的项目,则它内置了ts编译,这步省略)

    loaders: [
    	// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
    	{ test: /\.tsx?$/, loader: "awesome-typescript-loader" }
    ]
    复制代码
  4. 此时你能够写文件名为ts和tsx(React)后缀的代码了,它能够和现有的ES6代码共存,VSCode会自动校验这部分代码,webpack打包也没问题了。

  5. 逐渐的,开始打算重构之前的ES6代码为TS代码,只需将文件后缀改为ts(x)就行,就能够享受TS及IDE智能感知/纠错带来的好处。

更多迁移教程:官方迁移教程官方React项目迁移教程社区教程1社区教程2

新项目

  • 对于新项目,微软提供了很是棒的一些Starter项目,详细介绍了如何用TS和其余框架、库配合使用。若是是React项目,能够参考这个Starter:TypeScript-React-Starter

成本对比

星多表示占优

成本点 ES TS 说明
学习和踩坑成本 ※※※※※ ※※※ 虽然是JS超集,但仍是要学习TS自己及面向对象基础知识,开发环境搭建、使用中的问题和坑也须要本身趟,好在TS社区比较成熟,网上沉淀的资料不少
总体代码量 ※※※※※ ※※※※ TS代码增长比较完善的类型定义的话总体代码量比原生ES多5%~10%左右
原生JS(标准ES、浏览器端、服务器端) ※※※ ※※※※※ IDE内置了详尽的类型声明,能够智能提示方法和参数说明,提高了效率
依赖外部库(React、Lodash、Antd) ※※※ ※※※※※ 有TS类型声明库,IDE智能提示和分析,效率提高
内部公共库、模块 ※※※ ※※※※ 团队内部自行编写类型定义文件,有必定工做量,但开发效率能够有一些提高,逐步完善类型定义后,效率进一步提高
团队协做效率 ※※ ※※※※※ 对系统配置、外部接口、内部模块作类型定义后,实例对象属性就不能随意改了,每一个被调用方负责本身的对外类型展示(能够理解为形状),调用者只需关心被调用方的类型,不需关心内部细节
代码可维护性 ※※ ※※※※ 因为团队成员水平差别,和软件的的特质,长期迭代维护的项目总会遇到可维护性的问题,有了强类型约束和静态检查,以及智能IDE的帮助下,能够下降软件腐化的速度,提高可维护性,且在重构时,强类型和静态类型检查会帮上大忙,甚至有了类型定义,会不经意间增长重构的频率
运行时稳定性 ※※ ※※※※ 因为TS有静态类型检查,不少bug都会被消灭在上线前

小结

从上面的对比中能够看到,使用你们都熟悉的ES做为开发语言只在学习和踩坑成本以及总体代码量上占优,若是只是短时间项目,那用ES无可厚非,但咱们的项目生命周期持续好几年,是持续迭代升级的,目前TS社区已经比较成熟,学习资料也不少,并且TS带来的是内部协做开发效率、可维护性、稳定性的提高,因此从长远来看这个代价是值得付出的。并且各类类型声明定义文件的存在,是能够提高开发效率的;并且静态类型检查能够减小bug数量和排查bug的难度,变相也提高了效率,并且使整个项目相对变得更为稳定可控。

社区发展

从Stackoverflow的2017年开发者调查报告Google趋势npm下载量趋势上能够到看,TypeScript社区发展很快,特别是最近几年。特别是伴随着VS Code的诞生(TS写的,对TS支持很是友好),VS Code + TypeScript的组合让前端圈产生了一股清流,生产力和规范性获得了快速提高。从Google对TS的支持(Angular高于2的版本是TS写的)看到,国际大厂也是支持的。

从蚂蚁集团内部看,Ant Design、Basement等产品也是基于TS写的(至少是在大量使用),虽然有一些反对的声音,但整体仍是看好的,有合适的土壤就会快速发展,如Ant Design。

周边生态

类型声明包

React、及其余各类著名框架、库都有TS类型声明,咱们能够在项目中经过npm install @types/react方式安装,能够在这个网站搜索你想要安装的库声明包。安装后,写和那些框架、库相关的代码将会是一种很是爽的体验,函数的定义和注释将会自动提示出来,开发效率将会获得提高。

IDE

VS Code、WebStorm等前端圈流行的IDE都对TS有着很是友好的支持,VS Code甚至自身就是TS写成的。

深刻解读TS

TS语言设计目标

目标

编译期能够作静态检查,为大规模代码提供结构化装置,编译出符合习惯、易读的JS代码,和ECMAScript标准对齐,使用一向的、可删除的、结构化的类型系统,保护编译后的JS代码的运行时行为等等。

非目标

模仿现有语言,优化编译后代码的性能,应用“正确”的类型系统,增长运行时类型信息等等。

TS设计目标原文

TS简史

在最近几年,随着V8平台、各大现代浏览器的起来,JS的运行平台再不断完善,但,JS对于大型应用的开发是很是困难的,JS语言设计出来的目的不是为了大型应用,他是一门脚本语言,他没有静态类型校验,但更重要的是,他没有提供大型应用必须的classes、modules/namespaces、interfaces等结构化的装置,中间也出来过GWT等为了其余语言开发者开发大型JS应用的项目,这些项目可让你利用Java等面向对象语言开发大型Web应用,也能够利用到Eclipse等好用的IDE,但这些项目不是用JS写代码,因此若是你想用JS里的一些东西,你可能要比较费劲的在其余语言里把它给实现出来,因此咱们考虑如何加强JS语言,提供如静态类型检查、classes、modules/namespaces、interfaces等大型应用装置,这就是TS语言:**TS是一种开发大型JS应用的语言,更详细一点来讲,TS是有类型的编译到纯JS的JS超集。**因此通常来讲,JS代码也是TS代码。自己TS编译器也是TS写的,运行Node.js环境。【Anders Hejlsberg: Introducing TypeScript 2012

TS做者在最近微软Build大会给出的一个图:

JS feature间隔

如图,Web和Node平台的JS始终与JS最新规范有一段距离,Web平台的距离更远,TS能够填充这个间隙,让使用者在Web和Node平台都能用上最新的Feature,用上优雅的JS,提升生产力。【Anders Hejlsberg: What's new in TypeScript? 2017

和Flow 、Babel的对比

vs Flow

这篇文章能够看出,基础的类型检查功能发展到如今已经差异不大了,但在周边生态、文档完整性、社区资源方面TS赛过Flow。

vs Babel

Babel也是很不错的ES6 to 5编译工具,有不错的插件机制,社区发展也不错,但在一样一段代码编译出的JS代码里能够看到,TS编译后的代码是更符合习惯、简洁易读一些(都用的是官方网站的Playground工具)。我曾经维护过TS编译后的JS代码(TS源码丢失),感受还OK。

Babel编译后:

Babel编译

TS编译后:

TS编译

TS基础知识及核心概念

基础类型

let isDone: boolean = false;

let decimal: number = 6;

let color: string = "blue";

// 数组,有两种写法
let list: number[] = [1, 2, 3];
let list: Array<number> = [1, 2, 3];

// 元组(Tuple)
let x: [string, number] = ["hello", 10];

// 枚举
enum Color {Red = 1, Green = 2, Blue = 4}
let c: Color = Color.Green;

// 不肯定的能够先声明为any
let notSure: any = 4;

// 声明没有返回值
function warnUser(): void {
    alert("This is my warning message");
}

let u: undefined = undefined;

let n: null = null;

// 类型永远没返回
function error(message: string): never {
    throw new Error(message);
}

// 类型主张,就是知道的比编译器多,主动告诉编译器更多信息,有两种写法
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
let strLength: number = (someValue as string).length;
复制代码

更多介绍能够直接看官方文档

interface

TS中的一个核心原则之一就是类型检查关注的是值的形状,有时就叫作“鸭子辨型”(duck typing)或“结构化子类型”(structural subtyping)。TS中interface就承担了这样的角色,定义形状与约束,在内部使用或者和外部系统协做。一个例子:

interface SystemConfig {
  	attr1: string;
  	attr2: number;
    func1(): string;
    func2(): void;
}
复制代码

咱们给软件定了一个系统参数的配置接口,他定义了系统配置的形状,有两个属性attr1attr2,两个方法func1func2,这样若是定义了const systemConfig: SystemConfig = {},那systemConfig就不能随意修改了,他有形状了。

在Java中,咱们提倡面向接口编程,接口优于抽象类【Effective Java】,在TS的类系统中,接口也能够承担这样的角色,咱们能够用implements来实现接口,这样能够实现相似更为灵活的继承,如:

class A extends BaseClass implements BaseInterface1, BaseInterface2 {}
复制代码

类A继承了BaseClass,而且继承了BaseInterface1和BaseInterface2两个接口。

module/namespace

导出到外部的模块写法和ES6同样,内部模块如今推荐用namespace,如:

namespace Module1 {
  export interface SubModule1 {}
  
  export interface SubModule2 {}
}
const module: Module1.SubModule = {}
复制代码

命名空间在JS中用对象字面量也能够实现,早些年的不少JS库都是这种模式,但显然有了这种显示的命名空间声明,代码的易读性更好,且不能随意的改变,不像用原生JS对象时容易被覆盖。

访问权限控制

TS有着和传统面向对象语言相似的public、protected、private等访问权限,这个在大型应用中很实用,这里不展开。

其余

除了泛型相对难以掌握,其余class、decorator、async/await等都和ES六、ES7写法相似。

Type和Type System

TypeScript = Type + Script,那么编程语言中的Type是怎么定义的呢?

In computer science and computer programming, a data type or simply type is a classification of data which tells the compiler or interpreter how the programmer intends to use the data.【维基百科

在计算机科学中,数据类型或者简单说类型,是数据的类别,用来告诉编译器/解释器程序员想怎么使用数据。基本的数据类型如整数、布尔值、字符等,组合数据类型如数组、对象等,也有抽象数据类型如队列、栈、集合、字典等等。数据类型用在类型系统中,类型系统提供了类型定义、实现和使用的方式,每种编程语言都有各自的类型系统实现(若是有的话)。

咱们来看看Type System(类型系统)的定义:

In programming languages, a type system is a set of rules that assigns a property called type to the various constructs of a computer program, such as variables, expressions, functions or modules.[1] These types formalize and enforce the (otherwise implicit) categories the programmer uses for data structures and components (ex: "string", "array of float", "function returning boolean"). The main purpose of a type system is to reduce possibilities for bugs in computer programs[2] by defining interfaces between different parts of a computer program, and then checking that the parts have been connected in a consistent way. 【维基百科

在编程语言中,类型系统是一个规则集合,给程序中的变量、表达式、函数、模块等程序构建元素分配叫作类型的属性。这些类型明确并强制(也多是含蓄的)程序员如何使用数据结构。**类型系统的主要目的是经过定义程序不一样部分间协做的接口,并检查不一样部分以始终如一的方式协做,来减小程序可能产生的bug。**这种检查多是静态的(编译期)或动态的(运行时),或者既有静态的也有动态的。

类型系统的好处

检测错误

The most obvious benefit of static typechecking is that it allows early detection of some programming errors. Errors that are detected early can be fixed immediately, rather than lurking in the code to be discovered much later,when the programmer is in the middle of something else—or even after the program has been deployed. Moreover, errors can often be pinpointed more accurately during typechecking than at run time, when their effects may not become visible until some time after things begin to go wrong.【Types and Programming Languages

As your app grows, you can catch a lot of bugs with typechecking. 【React typechecking

静态类型检查最明显的好处是能够尽早的检查出程序中的错误。错误被尽早的检查出来可使它获得快速的修复,而不是潜伏在代码中,在中期甚至部署上线后才被发现。并且,错误在编译期能够被更精确的定位出来,而在运行时,错误产生的影响在程序出现问题前多是不容易被发现的。

程序会有各类各样的数据结构,若是改了一个数据类型,前端不少时候都是经过全局查找来处理这种重构问题的。而静态类型检查则可使再次编译后就能探知全部可能的错误,加上IDE的智能错误提示,重构起来更放心、更方便。

抽象化

Another important way in which type systems support the programming process is by enforcing disciplined programming. In particular, in the context of large-scale software composition, type systems form the backbone of the module languages used to package and tie together the components of large systems. Types show up in the interfaces of modules (and related structures such as classes); indeed, an interface itself can be viewed as “the type of a module,” providing a summary of the facilities provided by the module—a kind of partial contract between implementors and users.

Structuring large systems in terms of modules with clear interfaces leads to a more abstract style of design, where interfaces are designed and discussed independently from their eventual implementations. More abstract thinking about interfaces generally leads to better design.【Types and Programming Languages

类型系统支持编程阶段的另一个重要方式是强制让编程遵照纪律。在大规模软件系统中,类型系统组成了组件协做系统的脊梁。类型展示在模块(或者相关的结构如类)的接口中。接口能够看作“模块的类型”,展现了模块所能提供的功能,是一种实现者和用户间的合约。

在大量模块协做组成的大规模结构化软件系统中清晰的接口可使设计更为抽象,接口的设计和讨论独立于它们的实现。通常来讲,对接口更为抽象的思考可使得作出更好的设计。

Types enable programmers to think at a higher level than the bit or byte, not bothering with low-level implementation. For example, programmers can begin to think of a string as a set of character values instead of as a mere array of bytes. Higher still, types enable programmers to think about and express interfaces between two of any-sized subsystems. This enables more levels of localization so that the definitions required for interoperability of the subsystems remain consistent when those two subsystems communicate.【维基百科

类型会让程序员在一个更高的维度思考,而不是在底层的计算机实现细节纠缠。例如,咱们能够把字符串想成字符集,而不只仅是比特数组。更高维度,类型系统可让咱们用接口来思考和表达任意子系统/子程序之间的协做,接口定义可让子系统/子程序之间的通讯方式始终如一。

文档化

Types are also useful when reading programs. The type declarations in procedure headers and module interfaces constitute a form of documentation,giving useful hints about behavior. Moreover, unlike descriptions embedded in comments, this form of documentation cannot become outdated, since it is checked during every run of the compiler. This role of types is particularly important in module signatures.【Types and Programming Languages

类型对于阅读程序也是有用的。在程序头部的类型声明和模块接口造成了文档的形状,提供程序的行为提示。此外,不一样于在注释中的描述,这种形式的文档不会过时,由于每次编译都会校验,这在模块签名里特别重要。

In more expressive type systems, types can serve as a form of documentation clarifying the intent of the programmer. For example, if a programmer declares a function as returning a timestamp type, this documents the function when the timestamp type can be explicitly declared deeper in the code to be an integer type.【维基百科

在复用表现力的类型系统中,类型能够看作是一种描述程序员意图的表述方式。例如,咱们声明一个函数返回一个时间戳,这样就至关于明确说明了这个函数在更深层次的代码调用中会返回整数类型。

语言安全

The term “safe language” is, unfortunately, even more contentious than “type system.” Although people generally feel they know one when they see it, their notions of exactly what constitutes language safety are strongly influenced by the language community to which they belong. Informally, though, safe languages can be defined as ones that make it impossible to shoot yourself in the foot while programming.【Types and Programming Languages

安全语言这个说法是有争议的。受到该语言社区的严重影响。不正式的来讲,安全语言能够被定义为在编程时不可能从底层把本身杀死。

A type system enables the compiler to detect meaningless or probably invalid code. For example, we can identify an expression 3 / "Hello, World" as invalid, when the rules do not specify how to divide an integer by a string. Strong typing offers more safety, but cannot guarantee complete type safety.【维基百科

类型系统会容许编译器检查无心义或者可能不合法的代码。例如,咱们知道3/'hello world'不合法,强类型提供了更多的安全性,但也不能彻底作到类型安全。

效率

Static type-checking may provide useful compile-time information. For example, if a type requires that a value must align in memory at a multiple of four bytes, the compiler may be able to use more efficient machine instructions.【维基百科

静态类型检查会提供有用的编译期信息。例如,若是一个类型须要在内存中占四个字节,编译器可能会使用更有效率的机器指令。

静态类型、动态类型和弱类型、强类型

  • 静态类型:编译期就知道每个变量的类型。类型错误编译失败是语法问题。如Java、C++。
  • 动态类型:编译期不知道类型,运行时才知道。类型错误抛出异常发生在运行时。如JS、Python。
  • 弱类型:容忍隐式类型转换。如JS,1+'1'='11',数字型转成了字符型。
  • 强类型:不容忍隐式类型转换。如Python,1+'1'会抛出TypeError

接受TS

TS刚出来时我是有点抵触的,或者对她的感受就跟和CoffeeScriptDart等编译到JS语言差很少,感受就是其余语言往JS渗透的产物,近一两年,社区中TS的声音愈来愈强,而我也开始作大型JavaScript应用,随之逐渐从新认识TS,逐渐认识到TS的类型系统、TSC的静态检查、VS Code等IDE的强力支持对于开发出可维护性好、稳定性高的大型JavaScript应用的重要性。

权衡

如何更好的利用JS的动态性和TS的静态特质,咱们须要结合项目的实际状况来进行综合判断。一些建议:

  • 若是是中小型项目,且生命周期不是很长,那就直接用JS吧,不要被TS束缚住了手脚。
  • 若是是大型应用,且生命周期比较长,那建议试试TS。开源项目如VS CodeGitHub桌面端,不开源的如Slack桌面端AsanaPalantir
  • 若是是框架、库之类的公共模块,那更建议用TS了。如Ant DesignAngularIonic

至于到底用不用TS,仍是要看实际项目规模、项目生命周期、团队规模、团队成员状况等实际状况综合考虑。

原文地址:github.com/ProtoTeam/b…