温故知新之TypeScript(一)

写了 TypeScript 就不想再写 JavaScript —— 真的 !


本系列主要参考的是:
感谢xcatliu的开源书籍TypeScript 入门教程
感谢zhongsp的开源书籍TypeScript Handbook 中文版

目录

1. 第一部分

1. 是什么?

TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. Any browser. Any host. Any OS. Open source.

TypeScript是Microsoft公司注册商标。

TypeScript具有类型系统且是JavaScript的超集。 它可以编译成普通的JavaScript 代码。TypeScript支持任意浏览器,任意环境,任意系统并且是开源的。

1. 什么是类型系统

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.

类型系统是一种易处理的句法方法,通过根据它们计算的值的类型对短语进行分类来证明某些程序行为的缺失。

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

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

2. 静态类型系统是什么

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

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

3. 类型系统的益处
  1. 侦测错误: 静态类型分析首要优点就是能尽早的发现逻辑错误,而不是上线之后才发现;
  2. 抽象: 类型系统的另一个优点是强化规范编程,TypeScript 提供了简便的方式定义接口。这一点在大型软件开发时尤为重要,一个系统模块可以抽象的看做一个 TypeScript 定义的接口。
  3. 文档: 读程序时类型标注也有用处,不止是说人在读的时候。基于类型定义 IDE 可以对我们进行很多辅助,比如找到一个函数所有的使用,编写代码时对参数进行提示等等。
> npm install -g typedoc
> typedoc --out path/to/documentation/ path/to/typescript/project/


--out  指定输出位置 <path>
--name  指定生成的文档的title名称,会显示在文档logo处 <string>
--readme  指定reamme.md的位置,用于生成首页,不指定则文档不会有首页  <path>
--module  指定模块生成方式:<commonjs or amd>
--target  指定生成文档的js版本  <ES3 or ES5>
--exclude  排除指定文件  <path>
--theme  指定文档主题样式,可以使用内置的或自定义主题  <path/to/readme|none>
--includeDeclarations  解析.d.ts类型声明文件
--externalPattern  定义应该被认为是外部的文件的模式  <pattern>
--excludeExternals  阻止生成的文档外部解析的TypeScript被记录
--hideGenerator   请勿在页面末尾打印TypeDoc链接。
--verbose   生成文档时打印详细的日志
--gaID    设置Google Analytics跟踪ID并激活跟踪代码
--gaSite    设置Google Analytics的网站名称。默认为auto

2. 为什么选择 TypeScript

1. TypeScript 增加了代码的可读性和可维护性
1. 类型系统实际上是最好的文档,大部分的函数看看类型的定义就可以知道如何使用了;
2. 可以在编译阶段就发现大部分错误,这总比在运行时候出错好 
3. 增强了编辑器和 IDE 的功能,包括代码补全、接口提示、跳转到定义、重构等
2. TypeScript 非常包容
1. TypeScript 是 JavaScript 的超集,.js 文件可以直接重命名为 .ts
2. 自动做出类型推论 
3. 可以定义从简单到复杂的一切类型 即使 TypeScript 编译报错,也可以生成 JavaScript 文件 
4. 兼容第三方库,即使第三方库不是用 TypeScript 写的,也可以编写单独的类型

3. TypeScript 拥有活跃的社区
1. 大部分第三方库都有提供给 TypeScript 的类型定义文件 
2. Google 开发的 Angular2 就是使用 TypeScript 编写的 
3. ES6 的一部分特性是借鉴的 TypeScript 的(这条需要来源) 
4. TypeScript 拥抱了 ES6 规范,也支持部分 ES7 草案的规范
4. TypeScript 的缺点
1. 有一定的学习成本,需要理解接口(Interfaces)、泛型(Generics)、类 (Classes)、枚举类型(Enums)等前端工程师可能不是很熟悉的东西。
2. 而且它的中文资料也不多,短期可能会增加一些开发成本,毕竟要多写一些类型的定义,不过对于一个需 要长期维护的项目,TypeScript 能够减少其维护成本(这条需要来源) 
3. 集成到构建流程需要一些工作量 可能和一些库结合的不是很完美(这条需要举例)

整体来说,TS的 可读性、类型系统、ES6的兼容性;对比JS,会让你爱不释手。

3. 安装

npm install -g typescript

以上命令会在全局环境下安装 执行 tsc 命令了。 编译一个 TypeScript 文件很简单:

tsc hello.ts

主流的编辑器都支持 TypeScript,这里我推荐使用 Visual Studio Code,

谁用谁知道,之后再结合项目,介绍下基本使用。

第二部分

1. 基础数据类型

15368449834660.jpg

2. 数组、元组

1. 数组
// 两种表示方法
let list: number[] = [1, 2, 3];
let list: Array<number> = [1, 2, 3];
2. 元组

元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。

// Declare a tuple type
let x: [string, number];
// Initialize it
x = ['hello', 10]; // OK
// Initialize it incorrectly
x = [10, 'hello']; // Error

3. 枚举

eum类型是对JavaScript标准数据类型的一个补充。 像C#等其它语言一样,使 用枚举类型可以为一组数值赋予友好的名字

enum Color {Red, Green, Blue}

let c: Color = Color.Green;

默认情况下,从 0 开始为元素编号。 你也可以手动的指定成员的数值。 例如,我 们将上面的例子改成从 1 开始编号:

enum Color {Red = 1, Green, Blue}

let c: Color = Color.Green;
1. 数字枚举
enum Direction {

Up = 1,

Down,

Left,

Right

}
2. 字符串枚举
enum Direction {

Up = "UP",

Down = "DOWN",

Left = "LEFT",

Right = "RIGHT",

}

3. 接口

TypeScript的核心原则之一是对值所具有的结构进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。 在TypeScript里,接口的作用就是为这些类型【命名】和为你的代码或第三方代码【定义契约】。

1. 什么是接口

在面向对象语言中,【接口(Interfaces)】是一个很重要的概念,它是对行为的抽象, 而具体如何行动需要由类(classes)去实现(implements)。
TypeScript 中的接口是一个非常灵活的概念,除了可用于对类的一部分行为进行【抽象】以外,也常用于对「对象的形状(Shape)」进行描述。

2. 第一个例子

只读、必选、可选、任意限制

// test.ts
interface Person {
    // 只读属性
    readonly sex: string;
    // 必选
    name: string;
    // 可选
    age?: number;
    // 任意的string对应的any
    [propName: string]: any;
}

let tom: Person = {
    name: 'Tom',
    gender: 'male'
};

第二种情况,会出现问题


interface Person {
    name: string;
    // 此处报错: 
    // 任意属性的值允许是 string ,但是可选属性 age 的值却是 number , number 不是 string 的子属性,所以报错了。
    age?: number;
    [propName: string]: string;
}
// 属性“age”与索引签名不兼容。不能将类型“number”分配给类型“string”。
let tom: Person = {
    name: "Tom",
    age: 25,
    gender: "male"
};

为啥任意类型的值是any没问题? 每个属性不是独立的吗?为何可选类型必须是任意类型的子类型????

4. 泛型

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而 在使用的时候再指定类型的一种特性。

1. 第一个例子
function createArray(length: number, value: any): Array<any> {

let result = [];

for (let i = 0; i < length; i++) {

result[i] = value;

}

return result;

}

createArray(3, 'x'); // ['x', 'x', 'x']

这段代码编译不会报错,但是一个显而易见的缺陷是,它并没有准确的定义返回值 的类型:

Array<any> 允许数组的每一项都为任意类型。但是我们预期的是,数组中每一 项都应该是输入的 value 的类型。

2. <T>
function createArray<T>(length: number, value: T): Array<T> {

let result: T[] = [];

for (let i = 0; i < length; i++) {

result[i] = value;

}

return result;

}

// 指定类型
createArray<string>(3, 'x'); // ['x', 'x', 'x']
// 让类型推论自动推算出来
createArray(3, 'x'); // ['x', 'x', 'x']

上例中,我们在函数名后添加了 <T> ,其中 T 用来指代任意输入的类型,在后 面的输入 value: T 和输出 Array<T> 中即可使用了。

3. 第二个例子:多个类型参数
function swap<T, U>(tuple: [T, U]): [U, T] {

return [tuple[1], tuple[0]];

}

swap([7, 'seven']); // ['seven', 7]
4. 第三个例子: 泛型约束

在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法:

function loggingIdentity<T>(arg: T): T {

console.log(arg.length);

return arg;

}
// index.ts(2,19): error TS2339: Property 'length' does not exis
t on type 'T'.

限制的例子

interface Lengthwise {
    length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}

我们使用了 extends 形状,也就是必须包含 length
约束了泛型 属性。

TypeScript 学习资源合集

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 230,321评论 6 543
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,559评论 3 429
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 178,442评论 0 383
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,835评论 1 317
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,581评论 6 412
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,922评论 1 328
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,931评论 3 447
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 43,096评论 0 290
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,639评论 1 336
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,374评论 3 358
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,591评论 1 374
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 39,104评论 5 364
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,789评论 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 35,196评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,524评论 1 295
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,322评论 3 400
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,554评论 2 379

推荐阅读更多精彩内容

  • TypeScript 是 JavaScript 的一个超集,主要提供了类型系统和对 ES6 的支持,它由 Micr...
    Gukson666阅读 8,726评论 3 29
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,812评论 2 59
  • 使用标签名获得标签 使用标签名返回的是一个类似数组的选择集需要通过 下标取值的方法aLi[0].style.bac...
    会说话的乌鸦阅读 169评论 0 0
  • 需要软件 JDK 1.7+ Maven 3+ 1.使用start.spring.io创建Spring Boot应用...
    yiteng595阅读 369评论 0 0
  • 对世界充满憧憬与善意的女生总是活在一个美好的世界里。就像她,脸上洋溢着青春的微笑。 她是个自信的女孩,她自信她最美...
    Esther_Han阅读 167评论 0 1