TypeScript

TypeScript

TypeScript官网

TSD (全称为:TypeScript Definition manager for DefinitelyTyped)

它是借鉴NPM包管理工具的思想,实现了一个类似的包管理工具,我们不需要任何的学习成本,只管像使用NPM一样使用它。

TSD主页:你可以在这里深入了解它,或者是查询你所需要的模板库是否存在于TSD仓库。

1. 简单使用

安装

1
npm install tsd -g

安装我们需要的模板库

如jQuery和Angular的安装:

1
tsd install jquery angular --save

我们需要的依赖信息保存在一个叫tsd.json的文件,如NPM的package.json一样,方便于我们的版本管理,以及团队之间的共享。我们只需要共享这个tsd.json文件给其他同事,然后:

1
tsd install

2. install 问题解决

由于网络代理问题,无法访问github并下载.d.ts文件,解决方案如下:

.tsdrc文件

这是一个JSON文件,用来定义全局TSD配置信息。文件在用户目录 (eg: %USERPROFILE% on Windows, $HOME / ~ on Linux), 如果没有就新建一个.

Windows里建立.点开头的文件不允许,可以把文件命名为(.tsdrc.)后面多加个点,就可以变成.tsdrc文件了。

文件内容为:

1
2
3
{
"strictSSL": false
}

保存后再执行:

1
tsd install

基础

TypeScript基础类型文档

1. 基本类型

字符串

1
2
3
4
5
let name: string = `Gene`;
let age: number = 37;
let sentence: string = `Hello, my name is ${ name }.

I'll be ${ age + 1 } years old next month.`;

数组

1
2
3
let list: number[] = [1, 2, 3];

let list: Array<number> = [1, 2, 3];

元组 Tuple

1
2
3
4
5
6
7
8
9
// Declare a tuple type
let x: [string, number];
// Initialize it
x = ['hello', 10]; // OK
// Initialize it incorrectly
x = [10, 'hello']; // Error

console.log(x[0].substr(1)); // OK
console.log(x[1].substr(1)); // Error, 'number' does not have 'substr'

枚举

1
2
3
4
5
enum Color {Red, Green, Blue};
let c: Color = Color.Green;

enum Color {Red = 1, Green, Blue};
let colorName: string = Color[2];

任意值

1
2
3
4
5
6
7
8
9
10
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean

let notSure: any = 4;
notSure.ifItExists(); // okay, ifItExists might exist at runtime
notSure.toFixed(); // okay, toFixed exists (but the compiler doesn't check)

let prettySure: Object = 4;
prettySure.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object'.

空值

1
2
3
4
5
function warnUser(): void {
alert("This is my warning message");
}

let unusable: void = undefined;

类型断言

1
2
3
4
5
6
7
let someValue: any = "this is a string";

let strLength: number = (<string>someValue).length;

let someValue: any = "this is a string";

let strLength: number = (someValue as string).length;

2. 变量声明

解构数组

1
2
3
4
5
6
7
8
9
10
11
let input = [1, 2];
let [first, second] = input;
console.log(first); // outputs 1
console.log(second); // outputs 2

let o = {
a: "foo",
b: 12,
c: "bar"
}
let {a, b} = o;

默认值

1
2
3
function keepWholeObject(wholeObject: {a: string, b?: number}) {
let {a, b = 1001} = wholeObject;
}

3. 接口

1
2
3
4
5
6
7
8
9
10
interface LabelledValue {
label: string;
}

function printLabel(labelledObj: LabelledValue) {
console.log(labelledObj.label);
}

let myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj);

可选属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
interface SquareConfig {
color?: string;
width?: number;
}

function createSquare(config: SquareConfig): {color: string; area: number} {
let newSquare = {color: "white", area: 100};
if (config.color) {
newSquare.color = config.color;
}
if (config.width) {
newSquare.area = config.width * config.width;
}
return newSquare;
}

let mySquare = createSquare({color: "black"});

只读属性

1
2
3
4
interface Point {
readonly x: number;
readonly y: number;
}

实现接口

1
2
3
4
5
6
7
8
9
10
11
12
interface ClockInterface {
currentTime: Date;
setTime(d: Date);
}

class Clock implements ClockInterface {
currentTime: Date;
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) { }
}

4. 迭代器和生成器

for..of vs. for..in 语句

for..in迭代的是对象的键的列表,而for..of则迭代对象的键对应的值。

1
2
3
4
5
6
7
8
9
let list = [4, 5, 6];

for (let i in list) {
console.log(i); // "0", "1", "2",
}

for (let i of list) {
console.log(i); // "4", "5", "6"
}

5. 模块

TypeScript 1.5里术语名已经发生了变化。”内部模块”现在称做”命名空间”。”外部模块”现在则简称为”模块”。

模块在其自身的作用域里执行,而不是在全局作用域里;这意味着定义在一个模块里的变量,函数,类等等在模块外部是不可见的,除非你明确地使用export形式之一导出它们。相反,如果想使用其它模块导出的变量,函数,类,接口等的时候,你必须要导入它们,可以使用 import形式之一。

导出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
export interface StringValidator {
isAcceptable(s: string): boolean;
}
export const numberRegexp = /^[0-9]+$/;

export class ZipCodeValidator implements StringValidator {
isAcceptable(s: string) {
return s.length === 5 && numberRegexp.test(s);
}
}

class ZipCodeValidator implements StringValidator {
isAcceptable(s: string) {
return s.length === 5 && numberRegexp.test(s);
}
}
export { ZipCodeValidator };
export { ZipCodeValidator as mainValidator };

// 导出原先的验证器但做了重命名
export {ZipCodeValidator as RegExpBasedZipCodeValidator} from "./ZipCodeValidator";

导入

1
2
3
4
5
6
7
8
9
import { ZipCodeValidator } from "./ZipCodeValidator";

let myValidator = new ZipCodeValidator();

import { ZipCodeValidator as ZCV } from "./ZipCodeValidator";
let myValidator = new ZCV();

import * as validator from "./ZipCodeValidator";
let myValidator = new validator.ZipCodeValidator();

export = 和 import = require()

export =语法定义一个模块的导出对象。它可以是类,接口,命名空间,函数或枚举。

若要导入一个使用了export =的模块时,必须使用TypeScript提供的特定语法import let = require("module")

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let numberRegexp = /^[0-9]+$/;
class ZipCodeValidator {
isAcceptable(s: string) {
return s.length === 5 && numberRegexp.test(s);
}
}
export = ZipCodeValidator;

import zip = require("./ZipCodeValidator");

// Some samples to try
let strings = ["Hello", "98052", "101"];

// Validators to use
let validator = new zip();

// Show whether each string passed each validator
strings.forEach(s => {
console.log(`"${ s }" - ${ validator.isAcceptable(s) ? "matches" : "does not match" }`);
});

命名空间

1
2
3
4
5
namespace Validation {
export interface StringValidator {
isAcceptable(s: string): boolean;
}
}