成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

TypeScript 初識(shí)

iliyaku / 1287人閱讀

摘要:當(dāng)你陷在一個(gè)中大型項(xiàng)目中時(shí)應(yīng)用日趨成為常態(tài),沒(méi)有類(lèi)型約束類(lèi)型推斷,總有種牽一發(fā)而動(dòng)全身的危機(jī)和束縛。總體而言,這些付出相對(duì)于代碼的健壯性和可維護(hù)性,都是值得的。目前主流的都為的開(kāi)發(fā)提供了良好的支持,比如和。參考資料中文文檔

文章博客地址:http://pinggod.com/2016/Typescript/

TypeScript 是 JavaScript 的超集,為 JavaScript 的生態(tài)增加了類(lèi)型機(jī)制,并最終將代碼編譯為純粹的 JavaScript 代碼。類(lèi)型機(jī)制很重要嗎?最近的一些項(xiàng)目經(jīng)歷讓我覺(jué)得這真的很重要。當(dāng)你陷在一個(gè)中大型項(xiàng)目中時(shí)(Web 應(yīng)用日趨成為常態(tài)),沒(méi)有類(lèi)型約束、類(lèi)型推斷,總有種牽一發(fā)而動(dòng)全身的危機(jī)和束縛。Immutable.js 和 Angular 2 都在使用 TypeScript 做開(kāi)發(fā),它們都是體量頗大的項(xiàng)目,所以我決定嘗試一下 Typescript。此外我們還可以嘗試 Facebook 的 Flow,比較一下兩者的優(yōu)劣。Typescript 對(duì) ES6 也有良好的支持,目前組內(nèi)項(xiàng)目使用 Babel 編譯 ES6,這也就自然而然的把 TypeScirpt 和 Flow / babel-plugin-tcomb 放在了對(duì)立面,也許下一篇文章就是介紹 Flow 和 babel-plugin-tcomb。

What and Why

如果你想對(duì) TypeScript 有更深入的認(rèn)識(shí),那么推薦你閱讀 Stack Overflow 上的問(wèn)答 What is TypeScript and why would I use it in place of JavaScript? ,這一節(jié)也是對(duì)這篇問(wèn)答的一個(gè)簡(jiǎn)述。

雖然 JavaScript 是 ECMAScript 規(guī)范的標(biāo)準(zhǔn)實(shí)現(xiàn),但并不是所有的瀏覽器都支持最新的 ECAMScript 規(guī)范,這也就限制了開(kāi)發(fā)者使用最新的 JavaScript / ECMAScript 特性。TypeScript 同樣支持最新的 ECMAScript 標(biāo)準(zhǔn),并能將代碼根據(jù)需求轉(zhuǎn)換為 ES 3 / 5 / 6,這也就意味著,開(kāi)發(fā)者隨時(shí)可以使用最新的 ECMAScript 特性,比如 module / class / spread operator 等,而無(wú)需考慮兼容性的問(wèn)題。ECMAScript 所支持的類(lèi)型機(jī)制非常豐富,包括:interface、enum、hybird type 等等。

與 TypeScript 相似的工具語(yǔ)言還有很多,它們主要分為兩個(gè)陣營(yíng),一個(gè)是類(lèi)似 Babel 的陣營(yíng),以 JavaScript 的方式編寫(xiě)代碼,致力于為開(kāi)發(fā)者提供最新的 ECMAScript 特性并將代碼編譯為兼容性的代碼;另一個(gè)則是 Coffeescript、Clojure、Dart 等的陣營(yíng),它們的語(yǔ)法與 JavaScript 迥然不同,但最終會(huì)編譯為 JavaScript。TypeScript 在這兩者之間取得了一種平衡,它既為 JavaScript 增加了新特性,也保持了對(duì) JavaScript 代碼的兼容,開(kāi)發(fā)者幾乎可以直接將 .js 文件重命名為 .ts 文件,就可以使用 TypeScript 的開(kāi)發(fā)環(huán)境,這種做法一方面可以減少開(kāi)發(fā)者的遷移成本,一方面也可以讓開(kāi)發(fā)者快速上手 TypeScript。

JavaScript 是一門(mén)解釋型語(yǔ)言,變量的數(shù)據(jù)類(lèi)型具有動(dòng)態(tài)性,只有執(zhí)行時(shí)才能確定變量的類(lèi)型,這種后知后覺(jué)的認(rèn)錯(cuò)方法會(huì)讓開(kāi)發(fā)者成為調(diào)試大師,但無(wú)益于編程能力的提升,還會(huì)降低開(kāi)發(fā)效率。TypeScript 的類(lèi)型機(jī)制可以有效杜絕由變量類(lèi)型引起的誤用問(wèn)題,而且開(kāi)發(fā)者可以控制對(duì)類(lèi)型的監(jiān)控程度,是嚴(yán)格限制變量類(lèi)型還是寬松限制變量類(lèi)型,都取決于開(kāi)發(fā)者的開(kāi)發(fā)需求。添加類(lèi)型機(jī)制之后,副作用主要有兩個(gè):增大了開(kāi)發(fā)人員的學(xué)習(xí)曲線,增加了設(shè)定類(lèi)型的開(kāi)發(fā)時(shí)間。總體而言,這些付出相對(duì)于代碼的健壯性和可維護(hù)性,都是值得的。

目前主流的 IDE 都為 TypeScript 的開(kāi)發(fā)提供了良好的支持,比如 Visual Studio / VS Code、Atom、Sublime 和 WebStorm。TypeScript 與 IDE 的融合,便于開(kāi)發(fā)者實(shí)時(shí)獲取類(lèi)型信息。舉例來(lái)說(shuō),通過(guò)代碼補(bǔ)全功能可以獲取代碼庫(kù)中其他函數(shù)的信息;代碼編譯完成后,相關(guān)信息或錯(cuò)誤信息會(huì)直接反饋在 IDE 中……

在即將發(fā)布的 TypeScript 2.0 版本中,將會(huì)有許多優(yōu)秀的特性,比如對(duì) null 和 undefined 的檢查。cannot read property "x" of undefinedundefined is not a function 在 JavaScript 中是非常常見(jiàn)的錯(cuò)誤。在 TypeScript 2.0 中,通過(guò)使用 non-nullable 類(lèi)型可以避免此類(lèi)錯(cuò)誤:let x : number = undefined 會(huì)讓編譯器提示錯(cuò)誤,因?yàn)?undefined 并不是一個(gè) number,通過(guò) let x : number | undefined = undefinedlet x : number? = undefined 可以讓 x 是一個(gè) nullable(undefined 或 null) 的值。如果一個(gè)變量的類(lèi)型是 nullable,那么 TypeScript 編譯器就可以通過(guò)控制流和類(lèi)型分析來(lái)判定對(duì)變量的使用是否安全:

let x : number?;
if (x !== undefined)
    // this line will compile, because x is checked.
    x += 1;

// this line will fail compilation, because x might be undefined.    
x += 1;

TypeScript 編譯器既可以將 source map 信息置于生成的 .js 文件中,也可以創(chuàng)建獨(dú)立的 .map 文件,便于開(kāi)發(fā)者在代碼運(yùn)行階段設(shè)置斷點(diǎn)、審查變量。此外,TypeScript 還可以使用 decorator 攔截代碼,為不同的模塊系統(tǒng)生成模塊加載代碼,解析 JSX 等。

Usage

這一節(jié)介紹 TypeScirpt 的一些基礎(chǔ)特性,算是拋磚引玉,希望引起大家嘗試和使用 TypeScript 的興趣。首先,從最簡(jiǎn)單的類(lèi)型標(biāo)注開(kāi)始:

// 原始值
const isDone: boolean = false;
const amount: number = 6;
const address: string = "beijing";
const greeting: string = `Hello World`;

// 數(shù)組
const list: number[] = [1, 2, 3];
const list: Array = [1, 2, 3];

// 元組
const name: [string, string] = ["Sean", "Sun"];

// 枚舉
enum Color {
    Red,
    Green,
    Blue
};
const c: Color = Color.Green;

// 任意值:可以調(diào)用任意方法
let anyTypes: any = 4;
anyTypes = "any";
anyTypes = false

// 空值
function doSomething (): void {
    return undefined;
}

// 類(lèi)型斷言
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;

TypeScript 中的 Interface 可以看做是一個(gè)集合,這個(gè)集合是對(duì)對(duì)象、類(lèi)等內(nèi)部結(jié)構(gòu)的約定:

// 定義接口 Coords
// 該接口包含 number 類(lèi)型的 x,string 類(lèi)型的 y
// 其中 y 是可選類(lèi)型,即是否包含該屬性無(wú)所謂
interface Coords {
    x: number;
    y?: string;
};

// 定義函數(shù) where
// 該函數(shù)接受一個(gè) Coords 類(lèi)型的參數(shù) l
function where (l: Coords) {
    // doSomething
}

const a = { x: 100 };
const b = { x: 100, y1: "abc" };

// a 擁有 number 類(lèi)型的 x,可以傳遞給 where
where(a);
// b 擁有 number 類(lèi)型的 x 和 string 類(lèi)型的 y1,可以傳遞給 where
where(b);

// 下面這種調(diào)用方式將會(huì)報(bào)錯(cuò),雖然它和 where(b) 看起來(lái)是一致的
// 區(qū)別在于這里傳遞的是一個(gè)對(duì)象字面量
// 對(duì)象字面量會(huì)被特殊對(duì)待并經(jīng)過(guò)額外的屬性檢查
// 如果對(duì)象字面量中存在目標(biāo)類(lèi)型中未聲明的屬性,則拋出錯(cuò)誤
where({ x: 100, y1: "abc" });

// 最好的解決方式是為接口添加索引簽名
// 添加如下所示的索引簽名后,對(duì)象字面量可以有任意數(shù)量的屬性
// 只要屬性不是 x 和 y,其他屬性可以是 any 類(lèi)型
interface Coords {
    x: number;
    y?: string;
    [propName: string]: any
};

上面的代碼演示了接口對(duì)對(duì)象的約束,此外,接口還常用于約束函數(shù)的行為:

// CheckType 包含一個(gè)調(diào)用簽名
// 該調(diào)用簽名聲明了 getType 函數(shù)需要接收一個(gè) any 類(lèi)型的參數(shù),并最終返回一個(gè) string 類(lèi)型的結(jié)果
interface CheckType {
    (data: any): string;
};

const getType: CheckType = (data: any) : string => {
    return Object.prototype.toString.call(data);
}

getType("abc");
// => "[object String]"

與老牌強(qiáng)類(lèi)型語(yǔ)言 C#、Java 相同的是,Interface 也可以用于約束類(lèi)的行為:

interface ClockConstructor {
    new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
    tick();
}

function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
    return new ctor(hour, minute);
}

class DigitalClock implements ClockInterface {
    constructor(h: number, m: number) { }
    tick() {
        console.log("beep beep");
    }
}
class AnalogClock implements ClockInterface {
    constructor(h: number, m: number) { }
    tick() {
        console.log("tick tock");
    }
}

let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);
class

除了 ES6 增加的 Class 用法,TypeScript 還增加了 C++、Java 中常見(jiàn)的 public / protected / private 限定符,限定變量或函數(shù)的使用范圍。TypeScript 使用的是結(jié)構(gòu)性類(lèi)型系統(tǒng),只要兩種類(lèi)型的成員類(lèi)型相同,則認(rèn)為這兩種類(lèi)型是兼容和一致的,但比較包含 private 和 protected 成員的類(lèi)型時(shí),只有他們是來(lái)自同一處的統(tǒng)一類(lèi)型成員時(shí)才會(huì)被認(rèn)為是兼容的:

class Animal {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

class Rhino extends Animal {
    constructor() { super("Rhino"); }
}

class Employee {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

let animal = new Animal("Goat");
let rhino = new Rhino();
let employee = new Employee("Bob");

animal = rhino;
// Error: Animal and Employee are not compatible
animal = employee;

抽象類(lèi)是供其他類(lèi)繼承的基類(lèi),與接口不同的是,抽象類(lèi)可以包含成員方法的實(shí)現(xiàn)細(xì)節(jié),但抽不可以包含抽象方法的實(shí)現(xiàn)細(xì)節(jié):

abstract class Animal {
    // 抽象方法
    abstract makeSound(): void;
    // 成員方法
    move(): void {
        console.log("roaming the earch...");
    }
}
function

添加類(lèi)型機(jī)制的 TypeScript 在函數(shù)上最可以秀的一塊就是函數(shù)重載了:

let suits = ["hearts", "spades", "clubs", "diamonds"];

function pickCard(x: {suit: string; card: number; }[]): number;
function pickCard(x: number): {suit: string; card: number; };
function pickCard(x): any {
    // Check to see if we"re working with an object/array
    // if so, they gave us the deck and we"ll pick the card
    if (typeof x == "object") {
        let pickedCard = Math.floor(Math.random() * x.length);
        return pickedCard;
    }
    // Otherwise just let them pick the card
    else if (typeof x == "number") {
        let pickedSuit = Math.floor(x / 13);
        return { suit: suits[pickedSuit], card: x % 13 };
    }
}

let myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }];
let pickedCard1 = myDeck[pickCard(myDeck)];
let pickedCard2 = pickCard(15);

console.log("card: " + pickedCard1.card + " of " + pickedCard1.suit);
console.log("card: " + pickedCard2.card + " of " + pickedCard2.suit);

編譯器首先會(huì)嘗試匹配第一個(gè)函數(shù)重載的聲明,如果類(lèi)型匹配成功就執(zhí)行,否則繼續(xù)匹配其他的重載聲明,因此參數(shù)的針對(duì)性越強(qiáng)的函數(shù)重載,越要靠前聲明。

genrics
function identity(arg: T[]): T[] {
    console.log(arg.length);
    return arg;
}

let myIdentity: {(arg: T[]): T[]} = identity;

上面的代碼展示了泛型的基本用法,這里的 稱(chēng)為泛型變量,通過(guò)這個(gè)聲明,我們可以確定傳入的參數(shù)類(lèi)型和返回的數(shù)據(jù)類(lèi)型是一致的,一旦確定了傳入的參數(shù)類(lèi)型,也就確定了返回的數(shù)據(jù)類(lèi)型。myIdentity 使用了帶有調(diào)用簽名的對(duì)象字面量定義泛型函數(shù),實(shí)際上可以結(jié)合接口,寫(xiě)出更簡(jiǎn)潔的泛型接口:

interface IdentityFn {
     (arg: T[]): T[];
};

let myIdentity: IdentityFn = identity;

如果同一個(gè)泛型變量在接口中被反復(fù)使用,那么可以在定義接口名的同時(shí)聲明泛型變量:

interface IdentityFn {
    (arg: T[]): T[];
};

function identity(arg: T[]): T[] {
    console.log(arg.length);
    return arg;
}

let myIdentity: IdentityFn = identity;

在泛型接口之外,還可以使用泛型類(lèi),兩者的形式非常類(lèi)似:

class GenericNumber {
    zeroValue: T;
    add: (x: T, y: T) => T;
}

泛型也可以直接繼承接口約束自己的行為:

interface Lengthwise {
    length: number;
}

function loggingIdentity(arg: T): T {
    console.log(arg.length);
    return arg;
}
type inference

TypeScript 主要有兩種類(lèi)型推斷方式:Best Common Type 和 Contextual Type。我們先介紹 Best Common Type:

let x = [0, 1, null];

對(duì)于上面代碼中的變量 x,如果要推斷出它的類(lèi)型,就必須充分考慮 [0, 1, null] 的類(lèi)型,所以這里進(jìn)行類(lèi)型推斷的順序是從表達(dá)式的葉子到根的,也就是先推斷變量 x 的值都包含什么類(lèi)型,然后總結(jié)出 x 的類(lèi)型,是一種從下往上的推斷過(guò)程。

TypeScript 的類(lèi)型推論也可以按照從上往下的順序進(jìn)行,這被稱(chēng)為 Contextual Type

window.onmousedown = function(mouseEvent) {
    // Error: Property "button" does not exist ontype "MouseEvent"
    console.log(mouseEvent.buton);  
};

在上面的示例中,TypeScript 類(lèi)型推斷機(jī)制會(huì)通過(guò) window.onmousedown 函數(shù)的類(lèi)型來(lái)推斷右側(cè)函數(shù)表達(dá)式的類(lèi)型,繼而推斷出 mouseEvent 的類(lèi)型,這種從上到下的推斷順序就是 Contextual Type 的特征。

這里只對(duì) TypeScript 的特性做簡(jiǎn)單的介紹,更詳細(xì)的資料請(qǐng)參考以下資料:

TypeScript 官方文檔

TypeScript 中文文檔

TypeScript Language Specification

React and Webpack

在 TypeScript 中開(kāi)發(fā) React 時(shí)有以下幾點(diǎn)注意事項(xiàng):

對(duì) React 文件使用 .tsx 的擴(kuò)展名

在 tsconfig.json 中使用 compilerOptions.jsx: "react"

使用 typings 類(lèi)型定義

interface Props {
    foo: string;
}

class MyComponent extends React.Component {
    render() {
        return {this.props.foo}
    }
}

; // 正確

TypeScript 的官方文檔中對(duì) React 的開(kāi)發(fā)做了一個(gè)簡(jiǎn)單的演示,主要包含以下幾個(gè)部分:

使用 tsconfig.json 作為 TypeScript 的編譯配置文件

使用 webpack 作為構(gòu)建工具,需要安裝 webpack、ts-loader 和 source-map-loader

使用 typings 作為代碼提示工具

具體的搭建流程可以參考文檔 React & Webpack,此外,我個(gè)人寫(xiě)過(guò)一個(gè) TypeScript & Webpack & React 開(kāi)發(fā)的最小化模板可供各位參考,與之等同的 Babel & Webpack & React 版本。

如果查看模板之后對(duì) import * as React from "react" 的方式有所疑惑,請(qǐng)查看 TypeScript 的負(fù)責(zé)人 Anders Hejlsberg 在 issue#2242 中的詳細(xì)解析。

參考資料

TypeScript Document

What is TypeScript and why would I use it in place of JavaScript?

TypeScript 中文文檔

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/80012.html

相關(guān)文章

  • TypeScript 初識(shí) - 內(nèi)置對(duì)象

    摘要:自帶的內(nèi)置對(duì)象都可以直接在中當(dāng)作定義好的類(lèi)型。的內(nèi)置對(duì)象標(biāo)準(zhǔn)提供了常用的內(nèi)置對(duì)象等。在不需要額外引入就可以直接使用這些內(nèi)置對(duì)象用寫(xiě)不是內(nèi)置對(duì)象的一部分,想要寫(xiě)時(shí)提示,需要引入第三方聲明文件 JavaScript 自帶的內(nèi)置對(duì)象都可以直接在 TypeScript 中當(dāng)作定義好的類(lèi)型。 TypeScript 核心庫(kù)的定義文件 TypeScript 核心庫(kù)的定義文件定義了所有瀏覽器環(huán)境需要用...

    lordharrd 評(píng)論0 收藏0
  • TypeScript 初識(shí) - 基礎(chǔ)

    摘要:安裝通過(guò)命令進(jìn)行安裝創(chuàng)建文件文件名以擴(kuò)展名結(jié)尾編譯通過(guò)命令行進(jìn)行編譯通過(guò)運(yùn)行任務(wù)的方式進(jìn)行編譯下使用顯示運(yùn)行任務(wù),選擇構(gòu)建進(jìn)行編譯。 安裝 通過(guò) npm 命令進(jìn)行安裝: $ npm i -g typescript 創(chuàng)建 ts 文件 Typescript 文件名以 ts 擴(kuò)展名結(jié)尾: function hello(value: string) { console.log(`hel...

    CODING 評(píng)論0 收藏0
  • TypeScript 初識(shí) - 函數(shù)

    摘要:函數(shù)類(lèi)型函數(shù)返回值類(lèi)型我們可以給每個(gè)參數(shù)添加類(lèi)型之后再為函數(shù)本身添加返回值類(lèi)型。能夠根據(jù)返回語(yǔ)句自動(dòng)推斷出返回值類(lèi)型,所以通??梢允÷运涿瘮?shù)完整函數(shù)類(lèi)型完整的函數(shù)類(lèi)型包含兩部分參數(shù)類(lèi)型和返回值類(lèi)型。 函數(shù)是 JavaScript 的第一等公民,函數(shù)在 JavaScript 中可以實(shí)現(xiàn)抽象層、模擬類(lèi)、信息隱藏和模塊等等。TypeScript 在一定基礎(chǔ)上擴(kuò)展了函數(shù)的功能。 函數(shù)類(lèi)型 ...

    ARGUS 評(píng)論0 收藏0
  • TypeScript 初識(shí) - 變量

    摘要:通常會(huì)定義為函數(shù)的返回值一個(gè)類(lèi)型的變量是沒(méi)有生命用處的,因?yàn)轭?lèi)型的變量只能賦值為。和有一些區(qū)別的,函數(shù)沒(méi)有返回值時(shí)返回類(lèi)型為的方法,即使沒(méi)有寫(xiě)明語(yǔ)句,也會(huì)在函數(shù)執(zhí)行完的時(shí)候,隱式地返回一個(gè)類(lèi)型。中新增加的變量聲明方式。 類(lèi)型注解 類(lèi)型注解使用 :TypeAnnotation 語(yǔ)法。類(lèi)型聲明空間中可用的任何內(nèi)容都可以用作類(lèi)型注解。 const num: number = 123; fun...

    dinfer 評(píng)論0 收藏0
  • TypeScript 初識(shí) - 枚舉

    摘要:當(dāng)滿(mǎn)足以下條件時(shí),枚舉成員被當(dāng)作是常數(shù)不具有初始化函數(shù)并且之前的枚舉成員是常數(shù)。在這種情況下,當(dāng)前枚舉成員的值為上一個(gè)枚舉成員的值加。但第一個(gè)枚舉元素是個(gè)例外。枚舉成員使用常數(shù)枚舉表達(dá)式初始化。 數(shù)字類(lèi)型枚舉 常規(guī)枚舉的值都是數(shù)字類(lèi)型,因此被稱(chēng)為數(shù)字類(lèi)型枚舉: enum Color { Red, Blue, Green } console.log(Color.R...

    molyzzx 評(píng)論0 收藏0
  • TypeScript 初識(shí) - 接口

    摘要:接口的作用是聲明變量的結(jié)構(gòu)和方法,但不做具體的實(shí)現(xiàn)。這兩個(gè)使用場(chǎng)景不同。額外的屬性檢查從字面上的意思看,其實(shí)就是對(duì)接口未定義的屬性進(jìn)行檢查。上面的例子,定義了接口,它具有索引簽名。它不會(huì)幫你檢查類(lèi)是否具有某些私有成員。 接口的作用是聲明變量的結(jié)構(gòu)和方法,但不做具體的實(shí)現(xiàn)。通常,接口會(huì)強(qiáng)制對(duì)所有成員進(jìn)行類(lèi)型檢查,包括數(shù)量和類(lèi)型: interface Name { first: s...

    gnehc 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<