TypeScript入門

一粘勒、什么是 TypeScript讯柔?

  • 百度解釋:
    TypeScript是一種由微軟開發(fā)的自由和開源的編程語言钓觉。它是JavaScript的一個超集衔蹲,而且本質(zhì)上向這個語言添加了可選的靜態(tài)類型和基于類的面向?qū)ο缶幊?/a>离赫。它擴(kuò)展了JavaScript的語法芭逝,所以任何現(xiàn)有的JavaScript程序可以不加改變的在TypeScript下工作。TypeScript是為大型應(yīng)用之開發(fā)而設(shè)計渊胸,而編譯時它產(chǎn)生 JavaScript 以確保兼容性
  • 通俗解釋:
    TypeScript充分利用了JavaScript原有的對象模型并在此基礎(chǔ)上做了擴(kuò)充旬盯,添加了較為嚴(yán)格的類型檢查機(jī)制,添加了模塊支持和API導(dǎo)出的能力翎猛。比起JavaScript胖翰,TypeScript提供了更多在語言層面上的支持,使得程序員能夠以更加標(biāo)準(zhǔn)化的語法來表達(dá)語義上的約束切厘,從而降低了程序出錯的機(jī)率萨咳;TypeScript也使得代碼組織和復(fù)用變得更加有序,使得開發(fā)大型Web應(yīng)用有了一套標(biāo)準(zhǔn)方法疫稿。

二培他、TypeScript優(yōu)勢

  • 支持ES6(TypeScript腳本語言的語法會成為未來一段時間客戶端語言的主流語法)
  • 強(qiáng)大的IDE支持
  • Angular2框架的開發(fā)語言(學(xué)習(xí)Typescript語言幫你更好的幫你去學(xué)習(xí)Angular2的框架)
強(qiáng)大的IDE支持體現(xiàn)在三個特性上:

1.類型檢測
在Typescript里面是運(yùn)行為變量指定類型的鹃两,比如當(dāng)你為這個變量指定數(shù)字類型的值的時候,IDE會做出類型檢查舀凛,然后告訴你這里可能會有錯誤俊扳,這個特性會減少你在開發(fā)階段犯錯誤的幾率。
2.語法提示
在IDE里面去編寫TypeScript的代碼時猛遍,IDE會根據(jù)你當(dāng)前的上下文馋记,把你能用的類、變量螃壤、方法和關(guān)鍵字都給你提示出來抗果,你只要直接去選就可以了,這個特性會大大提升你的開發(fā)效率奸晴。
3.重構(gòu)
重構(gòu)是說你可以很方便的去修改你的變量或者方法的名字或者是文件的名字冤馏,當(dāng)你做出這些修改的時候,IDE會幫你自動引用這個變量或者調(diào)用這個方法地方的代碼自動幫你修改掉寄啼,這個特性一個是會提高你的開發(fā)效率逮光,另一個是可以很容易的提升你的代碼質(zhì)量。

三墩划、TypeScript缺點(diǎn)

  • 有一定的學(xué)習(xí)成本涕刚,需要理解接口(Interfaces)、泛型(Generics)乙帮、類(Classes)杜漠、枚舉類型(Enums)等前端工程師可能不是很熟悉的東西。而且它的中文資料也不多察净。
  • 短期可能會增加一些開發(fā)成本驾茴,畢竟要多寫一些類型的定義,不過對于一個需要長期維護(hù)的項目氢卡,TypeScript 能夠減少其維護(hù)成本锈至。
  • 集成到構(gòu)建流程需要一些工作量。
  • 可能和一些庫結(jié)合的不是很完美译秦。

四峡捡、TypeScript基礎(chǔ)語法

1.基礎(chǔ)類型

布爾值

布爾值是最基礎(chǔ)的數(shù)據(jù)類型,在 TypeScript 中筑悴,使用 boolean 定義布爾值類型

let isDone: boolean = false; 
數(shù)值

和JavaScript一樣们拙,TypeScript里的所有數(shù)字都是浮點(diǎn)數(shù)。 這些浮點(diǎn)數(shù)的類型是 number阁吝,除了支持十進(jìn)制和十六進(jìn)制字面量睛竣,還支持ECMAScript 2015中引入的二進(jìn)制和八進(jìn)制字面量。

let decLiteral: number = 6;  //十進(jìn)制
let hexLiteral: number = 0xf00d;   //十六進(jìn)制
let binaryLiteral: number = 0b1010; // ES6 中的二進(jìn)制表示法
let octalLiteral: number = 0o744;  // ES6 中的八進(jìn)制表示法

編譯結(jié)果

var decLiteral = 6;
var hexLiteral = 0xf00d;
var binaryLiteral = 10;
var octalLiteral = 484;

其中 0b10100o744ES6 中的二進(jìn)制和八進(jìn)制表示法求摇,它們會被編譯為十進(jìn)制數(shù)字射沟。

字符串

使用 string 定義字符串類型殊者,其中用 ` 來定義 ES6 中的模板字符串,${expr}用來在模板字符串中嵌入表達(dá)式验夯。

let myName: string = 'Wave';
let myAge: number = 23;
// 模板字符串
let sentence: string = `Hello, my name is ${myName}.
I'll be ${myAge + 1} years old next month.`;

編譯結(jié)果

var myName = 'Wave';
var myAge = 23;
// 模板字符串
var sentence = "Hello, my name is " + myName + ".\nI'll be " + (myAge + 1) + " years old next month.";
Void(空值)

JavaScript 沒有空值(Void)的概念猖吴,在 TypeScirpt 中,可以用 void 表示沒有任何返回值的函數(shù)挥转。

function warnUser(): void {
    alert("This is my warning message");
}

聲明一個void類型的變量沒有什么大用海蔽,因為你只能為它賦予 undefined 和 null:

let unusable: void = undefined;
Null 和 Undefined

TypeScript里,undefined和null兩者各自有自己的類型分別叫做undefinednull绑谣。
undefined 類型的變量只能被賦值為 undefined党窜,null 類型的變量只能被賦值為 null

let u: undefined = undefined;
let n: null = null;

與 void 的區(qū)別是,undefinednull是所有類型的子類型借宵。也就是說 undefined類型的變量幌衣,可以賦值給 number類型的變量:

// 這樣不會報錯
let u: undefined;
let num: number = u;
// 這樣會報錯
let u: void;
let num: number = u;
// index.ts(2,5): error TS2322: Type 'void' is not assignable to type 'number'.

注意:我們鼓勵盡可能地使用--strictNullChecks,因為指定了--strictNullChecks標(biāo)記,null和undefined只能賦值給void和它們各自壤玫。 這能避免很多常見的問題豁护。

Any 任意值

一個普通類型,在賦值過程中改變類型是不被允許的欲间,而any 類型楚里,則允許被賦值為任意類型。

//這樣會報錯
let myFavoriteNumber: string = 'seven';
myFavoriteNumber = 7;
//這樣不會報錯
let myFavoriteNumber: any = 'seven';
myFavoriteNumber = 7;
  • 聲明一個變量為任意值之后猎贴,對它的任何操作班缎,返回的內(nèi)容的類型都是任意值。
  • 變量如果在聲明的時候她渴,未指定其類型达址,那么它會被識別為任意值類型。
Never

never類型表示的是那些永不存在的值的類型惹骂。 例如苏携, neverr類型是那些總是會拋出異匙龅桑或根本就不會有返回值的函數(shù)表達(dá)式或箭頭函數(shù)表達(dá)式的返回值類型对粪; 變量也可能是 never類型,當(dāng)它們被永不為真的類型保護(hù)所約束時装蓬。
never類型是任何類型的子類型著拭,也可以賦值給任何類型;然而牍帚,沒有類型是never的子類型或可以賦值給never類型(除了never本身之外)儡遮。 即使 any也不可以賦值給never

// 返回never的函數(shù)必須存在無法達(dá)到的終點(diǎn)
function error(message: string): never {
    throw new Error(message);
}
// 推斷的返回值類型為never
function fail() {
    return error("Something failed");
}
// 返回never的函數(shù)必須存在無法達(dá)到的終點(diǎn)
function infiniteLoop(): never {
    while (true) {
    }
}
聯(lián)合類型

聯(lián)合類型(Union Types)表示取值可以為多種類型中的一種暗赶。聯(lián)合類型使用 | 分隔每個類型

let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;

當(dāng) TypeScript 不確定一個聯(lián)合類型的變量到底是哪個類型時鄙币,我們只能訪問此聯(lián)合類型的所有類型里共有的屬性或方法

//這樣會報錯
function getLength(something: string | number): number {
    return something.length;
}
//這樣不會報錯
function getString(something: string | number): string {
    return something.toString();
}

上例中l(wèi)ength 不是 string 和 number 的共有屬性肃叶,所以會報錯。訪問 string 和 number 的共有屬性是沒問題的十嘿。

聯(lián)合類型的變量在被賦值的時候因惭,會根據(jù)類型推論的規(guī)則推斷出一個類型:

let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
console.log(myFavoriteNumber.length); // 5
myFavoriteNumber = 7;
console.log(myFavoriteNumber.length); // 編譯時報錯

上例中,第二行的 myFavoriteNumber 被推斷成了 string绩衷,訪問它的 length 屬性不會報錯蹦魔。
而第四行的 myFavoriteNumber被推斷成了 number,訪問它的 length 屬性時就報錯了咳燕。

對象的類型——接口

在 TypeScript 中勿决,我們使用接口(Interfaces)來定義對象的類型

interface Person {
    name: string;
    age: number;
}

let tom: Person = {
    name: 'Tom',
    age: 25
};

我們定義了一個接口 Person,接著定義了一個變量 tom招盲,它的類型是 Person低缩。這樣,我們就約束了 tom 的形狀必須和接口 Person 一致宪肖。
定義的變量比接口少了一些屬性是不允許的表制,多一些屬性也是不允許的,賦值的時候控乾,變量的形狀必須和接口的形狀保持一致

interface Person {
    name: string;
    age: number;
}
//會編譯錯誤
let tom: Person = {
    name: 'Tom'
};
//會編譯錯誤
let tom: Person = {
    name: 'Tom',
    age: 25,
    gender: 'male'
};

有時我們希望不要完全匹配一個形狀么介,那么可以用可選屬性

interface Person {
   name: string;
   age?: number;
}

let tom: Person = {
   name: 'Tom'
};

可選屬性屬性的含義是該屬性可以不存在,但仍然不允許添加未定義的屬性

//編譯會報錯
interface Person {
    name: string;
    age?: number;
}
let tom: Person = {
    name: 'Tom',
    age: 25,
    gender: 'male'
};

有時候我們希望一個接口允許有任意屬性蜕衡,可以使用如下方式:

interface Person {
    name: string;
    age?: number;
    [propName: string]: any;
}

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

有時候我們希望對象中的一些字段只能在創(chuàng)建的時候被賦值壤短,那么可以用 readonly 定義只讀屬性

interface Person {
    readonly id: number;
    name: string;
    age?: number;
    [propName: string]: any;
}

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

tom.id = 9527; //會報錯

使用 readonly 定義的屬性 id 初始化后,又被賦值了慨仿,所以報錯了久脯。

數(shù)組類型

在 TypeScript 中,有兩種方式可以定義數(shù)組镰吆。 第一種帘撰,可以在元素類型后面接上[],表示由此類型元素組成的一個數(shù)組:

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

第二種方式是使用數(shù)組泛型万皿,Array<元素類型>

let list: Array<number> = [1, 2, 3];
函數(shù)的類型

在 JavaScript 中摧找,有兩種常見的定義函數(shù)的方式——函數(shù)聲明(Function Declaration)和函數(shù)表達(dá)式(Function Expression):

// 函數(shù)聲明(Function Declaration)
function sum(x, y) {
    return x + y;
}

// 函數(shù)表達(dá)式(Function Expression)
let mySum = function (x, y) {
    return x + y;
};
  • 函數(shù)聲明

一個函數(shù)有輸入和輸出,要在 TypeScript 中對其進(jìn)行約束牢硅,需要把輸入和輸出都考慮到蹬耘,其中函數(shù)聲明的類型定義較簡單:

function sum(x: number, y: number): number {
    return x + y;
}

注意,輸入多余的(或者少于要求的)參數(shù)减余,是不被允許的

function sum(x: number, y: number): number {
    return x + y;
}
sum(1, 2, 3);
// index.ts(4,1): error TS2346: Supplied parameters do not match any signature of call target.

function sum(x: number, y: number): number {
    return x + y;
}
sum(1);
// index.ts(4,1): error TS2346: Supplied parameters do not match any signature of call target.
  • 函數(shù)表達(dá)式

如果要我們現(xiàn)在寫一個對函數(shù)表達(dá)式(Function Expression)的定義综苔,可能會寫成這樣:

let mySum = function (x: number, y: number): number {
    return x + y;
};

這是可以通過編譯的,不過事實上,上面的代碼只對等號右側(cè)的匿名函數(shù)進(jìn)行了類型定義如筛,而等號左邊的 mySum堡牡,是通過賦值操作進(jìn)行類型推論而推斷出來的。如果需要我們手動給 mySum 添加類型杨刨,則應(yīng)該是這樣:

let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
    return x + y;
};

注意:不要混淆了 TypeScript 中的 => 和 ES6 中的 =>悴侵。
在 TypeScript 的類型定義中,=> 用來表示函數(shù)的定義拭嫁,左邊是輸入類型可免,需要用括號括起來,右邊是輸出類型做粤。
在 ES6 中浇借,=> 叫做箭頭函數(shù),應(yīng)用十分廣泛怕品,可以參考 ES6 中的箭頭函數(shù)妇垢。

  • 用接口定義函數(shù)的形狀

我們也可以使用接口的方式來定義一個函數(shù)需要符合的形狀:

interface SearchFunc {
    (source: string, subString: string): boolean;
}

let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
    return source.search(subString) !== -1;
}
  • 可選參數(shù)

前面提到,輸入多余的(或者少于要求的)參數(shù)肉康,是不允許的闯估。那么如何定義可選的參數(shù)呢?
與接口中的可選屬性類似吼和,我們用 ? 表示可選的參數(shù):

function buildName(firstName: string, lastName?: string) {
    if (lastName) {
        return firstName + ' ' + lastName;
    } else {
        return firstName;
    }
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');

需要注意的是涨薪,可選參數(shù)必須接在必需參數(shù)后面。換句話說炫乓,可選參數(shù)后面不允許再出現(xiàn)必須參數(shù)了

function buildName(firstName?: string, lastName: string) {
    if (firstName) {
        return firstName + ' ' + lastName;
    } else {
        return lastName;
    }
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName(undefined, 'Tom');
// index.ts(1,40): error TS1016: A required parameter cannot follow an optional parameter.
  • 參數(shù)默認(rèn)值

在 ES6 中刚夺,我們允許給函數(shù)的參數(shù)添加默認(rèn)值,TypeScript 會將添加了默認(rèn)值的參數(shù)識別為可選參數(shù)

function buildName(firstName: string, lastName: string = 'Cat') {
    return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');

此時就不受「可選參數(shù)必須接在必需參數(shù)后面」的限制了:

function buildName(firstName: string = 'Tom', lastName: string) {
    return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let cat = buildName(undefined, 'Cat');

關(guān)于默認(rèn)參數(shù)末捣,可以參考 ES6 中函數(shù)參數(shù)的默認(rèn)值侠姑。

  • 剩余參數(shù)

ES6 中,可以使用 ...rest 的方式獲取函數(shù)中的剩余參數(shù)(rest 參數(shù)):

function push(array, ...items) {
    items.forEach(function(item) {
        array.push(item);
    });
}

let a = [];
push(a, 1, 2, 3);

事實上箩做,items 是一個數(shù)組莽红。所以我們可以用數(shù)組的類型來定義它:

function push(array: any[], ...items: any[]) {
    items.forEach(function(item) {
        array.push(item);
    });
}

let a = [];
push(a, 1, 2, 3);

注意,rest 參數(shù)只能是最后一個參數(shù)邦邦,關(guān)于 rest 參數(shù)安吁,可以參考 ES6 中的 rest 參數(shù)

  • 重載

重載允許一個函數(shù)接受不同數(shù)量或類型的參數(shù)時圃酵,作出不同的處理柳畔。
比如馍管,我們需要實現(xiàn)一個函數(shù) reverse郭赐,輸入數(shù)字 123 的時候,輸出反轉(zhuǎn)的數(shù)字 321,輸入字符串 'hello' 的時候捌锭,輸出反轉(zhuǎn)的字符串 'olleh'俘陷。
利用聯(lián)合類型,我們可以這么實現(xiàn):

function reverse(x: number | string): number | string {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

然而這樣有一個缺點(diǎn)观谦,就是不能夠精確的表達(dá)拉盾,輸入為數(shù)字的時候,輸出也應(yīng)該為數(shù)字豁状,輸入為字符串的時候捉偏,輸出也應(yīng)該為字符串。
這時泻红,我們可以使用重載定義多個 reverse 的函數(shù)類型:

function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

上例中夭禽,我們重復(fù)定義了多次函數(shù) reverse,前幾次都是函數(shù)定義谊路,最后一次是函數(shù)實現(xiàn)讹躯。在編輯器的代碼提示中,可以正確的看到前兩個提示缠劝。
注意潮梯,TypeScript 會優(yōu)先從最前面的函數(shù)定義開始匹配,所以多個函數(shù)定義如果有包含關(guān)系惨恭,需要優(yōu)先把精確的定義寫在前面秉馏。

2.類型推論

如果沒有明確的指定類型,那么 TypeScript 會依照類型推論(Type Inference)的規(guī)則推斷出一個類型脱羡。

//雖然沒有指定類型沃饶,但是會在編譯的時候報錯
let myFavoriteNumber = 'seven';
myFavoriteNumber = 7;

// index.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.

//等價于以下代碼
let myFavoriteNumber: string = 'seven';
myFavoriteNumber = 7;

如果定義的時候沒有賦值,不管之后有沒有賦值轻黑,都會被推斷成 any 類型而完全不被類型檢查:

let myFavoriteNumber;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;

3.類型斷言

類型斷言(Type Assertion)可以用來手動指定一個值的類型糊肤。
語法<類型>值 或者 值 as 類型

例子:將一個聯(lián)合類型的變量指定為一個更加具體的類型
當(dāng) TypeScript 不確定一個聯(lián)合類型的變量到底是哪個類型的時候氓鄙,我們只能訪問此聯(lián)合類型的所有類型里共有的屬性或方法

function getLength(something: string | number): number {
    return something.length;
}
// index.ts(2,22): error TS2339: Property 'length' does not exist on type 'string | number'.
//   Property 'length' does not exist on type 'number'.

而有時候馆揉,我們確實需要在還不確定類型的時候就訪問其中一個類型的屬性或方法,比如:

function getLength(something: string | number): number {
    if (something.length) {
        return something.length;
    } else {
        return something.toString().length;
    }
}
// index.ts(2,19): error TS2339: Property 'length' does not exist on type 'string | number'.
//   Property 'length' does not exist on type 'number'.
// index.ts(3,26): error TS2339: Property 'length' does not exist on type 'string | number'.
//   Property 'length' does not exist on type 'number'.

上例中抖拦,獲取something.length的時候會報錯升酣。
此時可以使用類型斷言,將something 斷言成 string

function getLength(something: string | number): number {
    if ((<string>something).length) {
        return (<string>something).length;
    } else {
        return something.toString().length;
    }
}

類型斷言的用法如上态罪,在需要斷言的變量前加上<Type>即可
類型斷言不是類型轉(zhuǎn)換噩茄,斷言成一個聯(lián)合類型中不存在的類型是不允許的:

function toBoolean(something: string | number): boolean {
    return <boolean>something;
}
// index.ts(2,10): error TS2352: Type 'string | number' cannot be converted to type 'boolean'.
//   Type 'number' is not comparable to type 'boolean'.

4.聲明文件

當(dāng)使用第三方庫時,我們需要引用它的聲明文件复颈。
聲明語句
假如我們想使用第三方庫绩聘,比如 jQuery,我們通常這樣獲取一個 id 是 foo 的元素:

$('#foo');
// or
jQuery('#foo');

但是在 TypeScript 中,我們并不知道 $ 或 jQuery 是什么東西:

jQuery('#foo');

// index.ts(1,1): error TS2304: Cannot find name 'jQuery'.

這時凿菩,我們需要使用 declare 關(guān)鍵字來定義它的類型机杜,幫助 TypeScript 判斷我們傳入的參數(shù)類型對不對:

declare var jQuery: (selector: string) => any;

jQuery('#foo');

declare 定義的類型只會用于編譯時的檢查,編譯結(jié)果中會被刪除衅谷。上例的編譯結(jié)果是:

jQuery('#foo');

聲明文件
通常我們會把類型聲明放到一個單獨(dú)的文件中椒拗,這就是聲明文件:

// jQuery.d.ts
declare var jQuery: (string) => any;

我們約定聲明文件以 .d.ts 為后綴。
然后在使用到的文件的開頭获黔,用「三斜線指令」表示引用了聲明文件:

/// <reference path="./jQuery.d.ts" />
jQuery('#foo');

第三方聲明文件
當(dāng)然蚀苛,jQuery 的聲明文件不需要我們定義了,已經(jīng)有人幫我們定義好了:jQuery in DefinitelyTyped玷氏。我們可以直接下載下來使用枉阵,但是更推薦的是使用工具統(tǒng)一管理第三方庫的聲明文件。 TypeScript 2.0 推薦使用 @types 來管理预茄。
@types 的使用方式很簡單兴溜,直接用 npm 安裝對應(yīng)的聲明模塊即可,以 jQuery 舉例:

npm install @types/jquery --save-dev

5.內(nèi)置對象

JavaScript 中有很多內(nèi)置對象耻陕,它們可以直接在 TypeScript 中當(dāng)做定義好了的類型拙徽。
內(nèi)置對象是指根據(jù)標(biāo)準(zhǔn)在全局作用域(Global)上存在的對象。這里的標(biāo)準(zhǔn)是指 ECMAScript 和其他環(huán)境(比如 DOM)的標(biāo)準(zhǔn)诗宣。
ECMAScript 的內(nèi)置對象
ECMAScript 標(biāo)準(zhǔn)提供的內(nèi)置對象有:Boolean膘怕、ErrorDate召庞、RegExp等岛心。
我們可以在 TypeScript 中將變量定義為這些類型:

let b: Boolean = new Boolean(1);
let e: Error = new Error('Error occurred');
let d: Date = new Date();
let r: RegExp = /[a-z]/;

更多的內(nèi)置對象,可以查看 MDN 的文檔篮灼。
而他們的定義文件忘古,則在 TypeScript 核心庫的定義文件中。
DOM 和 BOM 的內(nèi)置對象
DOM 和 BOM 提供的內(nèi)置對象有:Document诅诱、HTMLElement髓堪、EventNodeList等娘荡。
TypeScript 中會經(jīng)常用到這些類型:

let body: HTMLElement = document.body;
let allDiv: NodeList = document.querySelectorAll('div');
document.addEventListener('click', function(e: MouseEvent) {
  // Do something
});

它們的定義文件同樣在 TypeScript 核心庫的定義文件中干旁。

TypeScript 核心庫的定義文件
TypeScript 核心庫的定義文件中定義了所有瀏覽器環(huán)境需要用到的類型,并且是預(yù)置在 TypeScript 中的炮沐。
當(dāng)你在使用一些常用的方法的時候争群,TypeScript 實際上已經(jīng)幫你做了很多類型判斷的工作了,比如:

Math.pow(10, '2');
//index.ts(1,14): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

上面的例子中大年,Math.pow 必須接受兩個 number類型的參數(shù)换薄。事實上 Math.pow的類型定義如下:

interface Math {
    /**
     * Returns the value of a base expression taken to a specified power.
     * @param x The base value of the expression.
     * @param y The exponent value of the expression.
     */
    pow(x: number, y: number): number;
}

再舉一個 DOM 中的例子:

document.addEventListener('click', function(e) {
    console.log(e.targetCurrent);
});
//index.ts(2,17): error TS2339: Property 'targetCurrent' does not exist on type 'MouseEvent'.

上面的例子中玉雾,addEventListener方法是在 TypeScript 核心庫中定義的:

interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEvent {
    addEventListener(type: string, listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
}

所以 e 被推斷成了 MouseEvent,而MouseEvent是沒有 targetCurrent 屬性的专控,所以報錯了。
注意遏餐,TypeScript 核心庫的定義中不包含 Node.js 部分伦腐。

用 TypeScript 寫 Node.js
Node.js 不是內(nèi)置對象的一部分,如果想用 TypeScript 寫 Node.js失都,則需要引入第三方聲明文件:

npm install @types/node --save-dev
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末柏蘑,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子粹庞,更是在濱河造成了極大的恐慌咳焚,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件庞溜,死亡現(xiàn)場離奇詭異革半,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)流码,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門又官,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人漫试,你說我怎么就攤上這事六敬。” “怎么了驾荣?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵外构,是天一觀的道長。 經(jīng)常有香客問我播掷,道長审编,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任歧匈,我火速辦了婚禮割笙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘眯亦。我一直安慰自己伤溉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布妻率。 她就那樣靜靜地躺著乱顾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宫静。 梳的紋絲不亂的頭發(fā)上走净,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天券时,我揣著相機(jī)與錄音,去河邊找鬼伏伯。 笑死橘洞,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的说搅。 我是一名探鬼主播炸枣,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼弄唧!你這毒婦竟也來了适肠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤候引,失蹤者是張志新(化名)和其女友劉穎侯养,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體澄干,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡逛揩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了麸俘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片息尺。...
    茶點(diǎn)故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖疾掰,靈堂內(nèi)的尸體忽然破棺而出搂誉,到底是詐尸還是另有隱情,我是刑警寧澤静檬,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布炭懊,位于F島的核電站,受9級特大地震影響拂檩,放射性物質(zhì)發(fā)生泄漏侮腹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一稻励、第九天 我趴在偏房一處隱蔽的房頂上張望父阻。 院中可真熱鬧,春花似錦望抽、人聲如沸加矛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽斟览。三九已至,卻和暖如春辑奈,著一層夾襖步出監(jiān)牢的瞬間苛茂,已是汗流浹背已烤。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留妓羊,地道東北人胯究。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像躁绸,于是被迫代替她去往敵國和親裕循。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內(nèi)容