前言
2015 年末看过一篇文章《ES2015 & babel 实战:开发 npm 模块》,那时刚接触 ES6 不久,发觉新的 ES6 语法大大简化了 JavaScript 程序的表达方式,比如箭头函数、class、async/await、Proxy等新特性,从此写 JavaScript 更成了一种享受。但是在近一年半的实践中,发现多人维护一个大型项目时,除了使用 ES6 新特性更简单地实现功能之外,另一个重要的事情是如何保证程序的健壮性和可维护性,在这点上,完全无类型检查、表达方式极其灵活的 JavaScript 却显得有点吃力,尤其是当团队人员水平参差不齐时更为严重。后来接触到了 TypeScript,它是 JavaScript 语言的超集,除了支持最新的JavaScript 语言特性之外,还增加了非常有用的编译时类型检查特性,而代码又最终会编译成 JavaScript 来执行,非常适合原本使用 JavaScript 来开发的大型项目。
我在经过半年多的深入实践,总结了一些使用 TypeScript 的经验,写成了这一篇文章,希望帮助TypeScript 初学者更轻松地学习。
什么是 TypeScript
TypeScript 是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。安德斯·海尔斯伯格,C#的首席架构师,已工作于 TypeScript 的开发。2012 年十月份,微软发布了首个公开版本的 TypeScript,2013 年 6 月 19 日,在经
历了一个预览版之后微软正式发布了正式版 TypeScript 0.9,向未来的 TypeScript 1.0 版迈进了很大一步。
以上解释来源于百度百科 TypeScript 词条
结合微软开发的开源代码编辑器 Visual Studio Code,使用 TypeScript 开发项目具有以下优点:
可以使用最新的 ES2017 语言特性
非常精准的代码提示
编辑代码时具有及时错误检查功能,可以避免诸如输错函数名这种明显的错误
非常精准的代码重构功能
非常方便的断点调试功能
编辑器集成调试功能
在使用 TypeScript 编写 Node.js 项目时,由于长期使用 JavaScript 而养成随便在对象上附加各种东西的坏习惯,刚使用 TypeScript 时可能会有点不适,另一个不可避免的问题是依赖的代码库不是使用TypeS
cript 编写的,由于不能直接通过 import 引用这些模块,在 TypeScript 上使用时会造成一些困难。本文将对初学 TypeScript 时可能会关注的问题作简要的说明。
编写本文时最新的 TypeScript 版本为 v2.2.2,Node.js 最新 LTS 版本为 v6.10.2,本文的所有示例代码将基于该环境来运行。
TypeScript 语言走马观花
在学习 TypeScript 前,你需要熟悉 ES6 语法,如果之前未接触过 ES6 可以参考我之前写过的文章《ES2015 & babel 实战:开发 npm 模块》及 ES6 语法相关的教程《ECMAScript 6 入门》。可以使用TypeScript 提供的 Playround 工具在线查看 TypeScript 编译为 JavaScript 后的代码,对初学者了解 TypeScript 尤为有用。
其实在 TypeScript 中是可以完全使用纯 JavaScript 语法的(当然如果这样的话就达不到使用TypeScript 的目的,但是在项目重构为 TypeScript 的初期可以实现 TypeScript 与 JavaScript 并存,逐步替换),比如我们在 Playground 中输入以下代码:
function hello(msg) {
console.log("hello, " + msg);
}
hello('laolei');
可以看到输出的 JavaScript 代码也跟输入的一模一样。
简单来理解,TypeScript 中的 Type 指的就是在 JavaScript 语法的基础上,增加了静态类型检查,而为了让 TypeScript 起到其应有的作用,在编写程序时我们也加上必要的类型声明,比如:
function hello(msg: string): void {
console.log(`hello, ${msg}`);
}
hello('laolei');
上例中声明了函数的参数msg为string类型,而返回值为void(没有返回值),可以看到编译后的代码还是与前面例子一样,并没有变化。如果我们将函数调用部分改为hello(123),将会看到参数123下面画了红线:
编译器报错Argument of type '123' is not assignable to parameter of type 'string'(参数123不能赋值给string类型),因为123是number类型。需要注意的是,这个错误是在编译代码时发生的,但是 TypeScript 仍然会继续将代码编译为 JavaScript,可以看到编译后的代码也没有变化,**这表明TypeScript 的类型检查是在编译期进行的,编译后的 JavaScript 代码并不会增加任何类型检查相关的代码,因此我们并不需要担心由此带来的性能问题。**也就是说,如果我们的 TypeScript 项目编译成了JavaScript 再被其他的 JavaScript 程序调用,而对方传递了不合法的数据类型,程序可能会抛出异常。
我们可以尝试将参数部分msg: string改为msg: any,这时编译器没有给出任何错误,因为**any表示了此参数接受任意类型**。这在使用一些 JavaScript 项目时尤其有用,可以短时间内降低使用TypeScript 的难度,但是我们应该尽量避免这样用。
TypeScript 中的类型分为基础类型、接口、类、函数、泛型、枚举等几种:
基础类型
以下是 TypeScript 中的几种基础类型:
boolean为布尔值类型,如let isDone: Boolean = false
number为数值类型,如let decimal: number = 6;
string为字符串类型,如let color: string = 'blue'
数组类型,如let list: number[] = [ 1, 2, 3 ]
元组类型,如let x: [ string, number ] = [ "hello", 10 ]
枚举类型,如enum Color { Red, Green, Blue }; let c: Color = Color.Green
any为任意类型,如let notSure: any = 4; notSure = "maybe a string instead"
void为空类型,如let unusable: void = undefined
null和undefined
never表示没有值的类型,如function error(message: string): never { throw new
Error(message); }
多种类型可以用|隔开,比如number | string表示可以是number或string类型
never类型是 TypeScript 2.0 新增的,并不如前面几种类型那么常用,详细信息可以参考这里:TypeScript Handbook - Basic Types - Never
接口(interface)
以下是接口的几种常见形式:
// 定义具有 color 和 width 属性的对象
interface SuperConfug {
color: string;
width: number;
}
// readonly 表示只读,不能对其属性进行重新赋值
interface Point {
readonly x: number;
readonly y: number;
}
// ?表示属性是可选的,
// [propName: string]: any 表示允许 obj[xxx] 这样的动态属性
interface SquareConfig {
color?: string;
width?: number;
[propName: string]: any;
编程入门先学js}
// 函数接口
interface SearchFunc {
(source: string, subString: string): boolean;
}
实际上 TypeScript 的接口还有很多种的表示形式,详细信息可以参考这里:TypeScript Hankbook - Interfaces
函数
以下是几种函数接口的定义方式:
// 普通函数
function add(a: number, b: number): number {
return a + b;
}
// 函数参数
function readFile(file: string, callback: (err: Error | null, data: Buffer) => void) {
}
// 通过 type 语句定义类型
type CallbackFunction = (err: Error | null, data: Buffer) => void;
function readFile(file: string, callback: CallbackFunction) {
}
// 通过 interface 语句来定义类型
interface CallbackFunction {
(err: Error | null, data: Buffer): void;
}
function readFile(file: string, callback: CallbackFunction) {
}
以上几种定义方式有着微妙的差别,还是需要在深入实践 TypeScript 后才能合理地运用。详细信息可以参考这里:TypeScript Handbook - Functions
TypeScript 的类定义跟 JavaScript 的定义方法类型一样,但是增加了public, private, protected, readonly等访问控制修饰符:
class Person {
protected name: string;
constructor(name: string) {
this.name = name;
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。