typescript之旅
1.TypeScript-Basic
2.TypeScript interface
3.Typescript-module(1)
4.TypeScript Modules(2)
5.Typescript tsconfig
6.TypeScript Functions
7.Typescript Class
TypeScript-Modules(2).md
Module
CMD和AMD外部依賴模組
如果你並沒有使用node.js或require.js,那就沒有必要使用module關鍵字了,只需要使用namespace
-
namespace中使用reference,module使用
import someMod = require(`someModule`);
-
export功能不變,使module內部宣告外部可見
-
編譯module,必須指定–module引數
tsc --module commonjs Test.ts
tsc --module amd Test.ts
-
編譯器根據import語句,順序匯入依賴檔案
Validation.ts
export interface StringValidator {
isAcceptable(s: string): boolean;
}
LettersOnlyValidator.ts
import validation = require(`./Validation`);
var lettersRegexp = /^[A-Za-z]+$/;
export class LettersOnlyValidator implements validation.StringValidator {
isAcceptable(s: string) {
return lettersRegexp.test(s);
}
}
ZipCodeValidator.ts
import validation = require(`./Validation`);
var numberRegexp = /^[0-9]+$/;
export class ZipCodeValidator implements validation.StringValidator {
isAcceptable(s: string) {
return s.length === 5 && numberRegexp.test(s);
}
}
Test.ts
import validation = require(`./Validation`);
import zip = require(`./ZipCodeValidator`);
import letters = require(`./LettersOnlyValidator`);
// Some samples to try
var strings = [`Hello`, `98052`, `101`];
// Validators to use
var validators: { [s: string]: validation.StringValidator; } = {};
validators[`ZIP code`] = new zip.ZipCodeValidator();
validators[`Letters only`] = new letters.LettersOnlyValidator();
// Show whether each string passed each validator
strings.forEach(s => {
for (var name in validators) {
console.log(`"` + s + `" ` + (validators[name].isAcceptable(s) ? ` matches ` : ` does not match `) + name);
}
});
上述語法typescript編譯器是如何生成程式碼的?
demo:
SimpleModule.ts
import m = require(`mod`);
export var t = m.something + 1;
AMD / RequireJS SimpleModule.js:
define(["require", "exports", `mod`], function(require, exports, m) {
exports.t = m.something + 1;
});
CommonJS / Node SimpleModule.js:
var m = require(`mod`);
exports.t = m.something + 1;
簡化上面的例子
export= 語法
-
在LettersOnlyValidator.ts中有下面的程式碼
import validation = require(`./Validation`);
...
validation. StringValidator.doSometing();
同時我們發現上面例子的兩種validator,每個module都只匯出一個class宣告。如果使用上面的方式匯出,其他檔案import之後,每次都使用validation. StringValidator
顯得很沉重
Validation.ts
export interface StringValidator {
isAcceptable(s: string): boolean;
}
LettersOnlyValidator.ts
import validation = require(`./Validation`);
var lettersRegexp = /^[A-Za-z]+$/;
class LettersOnlyValidator implements validation.StringValidator {
isAcceptable(s: string) {
return lettersRegexp.test(s);
}
}
export = LettersOnlyValidator;
ZipCodeValidator.ts
import validation = require(`./Validation`);
var numberRegexp = /^[0-9]+$/;
class ZipCodeValidator implements validation.StringValidator {
isAcceptable(s: string) {
return s.length === 5 && numberRegexp.test(s);
}
}
export = ZipCodeValidator;
Test.ts(此檔案是重點,zipValidator和lettersValidator可以直接使用)
import validation = require(`./Validation`);
import zipValidator = require(`./ZipCodeValidator`);
import lettersValidator = require(`./LettersOnlyValidator`);
// Some samples to try
var strings = [`Hello`, `98052`, `101`];
// Validators to use
var validators: { [s: string]: validation.StringValidator; } = {};
validators[`ZIP code`] = new zipValidator();
validators[`Letters only`] = new lettersValidator();
// Show whether each string passed each validator
strings.forEach(s => {
for (var name in validators) {
console.log(`"` + s + `" ` + (validators[name].isAcceptable(s) ? ` matches ` : ` does not match `) + name);
}
});
注意
這種簡化寫法只使用於只匯出一個宣告的模組
別名
-
另一種縮短物件引用名稱的方式。
注意
別名的語法也是很奇葩的,如果名稱太長,可以使用import q = x.y.z
,這個語法和import x = require(`name`)
沒有一毛錢關係,typescript專案組的朋友們,你們加個關鍵字能死嗎?這裡的語法只是為指定的符號建立一個別名。
module Shapes {
export module Polygons {
export class Triangle { }
export class Square { }
}
}
import polygons = Shapes.Polygons;
var sq = new polygons.Square(); // Same as `new Shapes.Polygons.Square()`
高階模組載入方式
有時候,你緊緊想在滿足某些條件下,才載入某一模組
這個功能確實很贊,但是還是語法的問題,很讓你困惑。
再說之前呢,有必要對這個語法進行深入瞭解
import zipValidator = require(`./ZipCodeValidator`);
按照上面的理解,大多數人肯定認為,這個語法就是nodejs中的var zipValidator = require(`./ZipCodeValidator`);
這樣理解也沒錯,但是這裡有一個typescript的惰性載入問題。首先我們知道node載入外部模組是很浪費時間的,所以呢,typescript遇到這句話,並不會馬上進行require呼叫,而是等到後面真的要用的該模組時,才會require.看例子:
Test.ts
import StringValidator = require(`./Validation`);
import zipValidator = require(`./ZipCodeValidator`);
import lettersValidator = require(`./LettersOnlyValidator`);
// Some samples to try
var strings = [`Hello`, `98052`, `101`];
// Validators to use
var validators: { [s: string]: StringValidator; } = {};
validators[`ZIP code`] = new zipValidator();
裡面的lettersValidator
雖然匯入了,但是後面並沒有使用。
生成的js程式碼如下:
var zipValidator = require(`./ZipCodeValidator`);
// Some samples to try
var strings = [`Hello`, `98052`, `101`];
// Validators to use
var validators = {};
validators[`ZIP code`] = new zipValidator();
ok,這就是我們要了解的背景,typescript的惰性載入問題
利用上面的這個特性,我們實現動態載入(nodejs和requirejs的區別)
Dynamic Module Loading in node.js
declare var require;
import Zip = require(`./ZipCodeValidator`);
if (needZipValidation) {
var x: typeof Zip = require(`./ZipCodeValidator`);
if (x.isAcceptable(`.....`)) { /* ... */ }
}
Sample: Dynamic Module Loading in require.js
declare var require;
import Zip = require(`./ZipCodeValidator`);
if (needZipValidation) {
require([`./ZipCodeValidator`], (x: typeof Zip) => {
if (x.isAcceptable(`...`)) { /* ... */ }
});
}
-
雖然我前面鋪墊了很多,你看到這裡,還是可能看不懂,好吧,我承認我自己在這裡也糾結了好久
declare var require
是表示宣告nodejs中的require關鍵詞,否則這裡var x: typeof Zip = require(`./ZipCodeValidator`);
,會報錯(require未宣告)。
-
請注意這裡的require是node中的require,而
import Zip = require(`./ZipCodeValidator`);
中的require是typescript的關鍵詞,而且只能和import一起用。瞭解這點非常重要!!! -
import Zip = require(`./ZipCodeValidator`);
根據惰性載入機制,這句話什麼都不會做!!! -
typeof Zip
什麼意思,請回頭看高階技巧
生成的js程式碼
if (needZipValidation) {
var x = require(`./ZipCodeValidator`);
if (x.isAcceptable(`.....`)) { }
}
使用第三方庫
第三方庫都不是typescript開發的,我們要使用的時候怎麼使用呢?
第三方庫api都是沒有型別資訊的,但是typescript編譯器主要的工作就是檢查型別是否匹配。我們能不能把它們的api全部宣告一遍,這樣我們的程式碼呼叫api的時候,編譯器去檢查宣告型別是否一致,來提示錯誤。
所以要寫.d.ts檔案,比如D3,那就要寫D3.d.ts
-
namespace
D3.d.ts (simplified excerpt)
declare namespace D3 {
export interface Selectors {
select: {
(selector: string): Selection;
(element: EventTarget): Selection;
};
}
export interface Event {
x: number;
y: number;
}
export interface Base extends Selectors {
event: Event;
}
}
declare var d3: D3.Base;
-
module
node.d.ts (simplified excerpt)
declare module "url" {
export interface Url {
protocol?: string;
hostname?: string;
pathname?: string;
}
export function parse(urlStr: string, parseQueryString?, slashesDenoteHost?): Url;
}
declare module "path" {
export function normalize(p: string): string;
export function join(...paths: any[]): string;
export var sep: string;
}
Now we can /// <reference> node.d.ts and then load the modules using e.g. import url = require(`url`);.
///<reference path="node.d.ts"/>
import url = require("url");
var myUrl = url.parse("http://www.typescriptlang.org");