TypeScript Modules(2)

typescript之旅

1.TypeScript-Basic
2.TypeScript interface
3.Typescript-module(1)
4.TypeScript Modules(2)
5.Typescript tsconfig
6.TypeScript Functions
7.Typescript Classjavascript

TypeScript-Modules(2).md

Module

CMD和AMD外部依賴模塊
若是你並無使用node.js或require.js,那就沒有必要使用module關鍵字了,只須要使用namespacejava

  • namespace中使用reference,module使用
    import someMod = require('someModule');node

  • export功能不變,使module內部聲明外部可見typescript

  • 編譯module,必須指定--module參數segmentfault

tsc --module commonjs Test.ts
tsc --module amd Test.ts
  • 編譯器根據import語句,順序導入依賴文件api

Validation.tsrequirejs

export interface StringValidator {
    isAcceptable(s: string): boolean;
}

LettersOnlyValidator.tsui

import validation = require('./Validation');
var lettersRegexp = /^[A-Za-z]+$/;
export class LettersOnlyValidator implements validation.StringValidator {
    isAcceptable(s: string) {
        return lettersRegexp.test(s);
    }
}

ZipCodeValidator.tsurl

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.tsspa

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");
相關文章
相關標籤/搜索