一.interface
一般情況: 不允許多屬性也不允許少屬性
interface Person {
name: string,
age: number
}
let james: Person {
name: 'james'
} // 錯誤, 少了age屬性
let james: Person {
name: 'james'
age: 27,
job: 'bricks diliver'
} // 錯誤躯畴, 多了屬性
如果想要某個屬性可選尊惰,可用 ?
interface Person {
name: string,
age?: number // 變?yōu)榭蛇x
}
let james: Person {
name: 'james'
} // 沒毛病 老鐵
let james: Person {
name: 'james'
age: 27,
job: 'bricks diliver'
} // 錯誤娄帖, 可以少屬性瘦材, 多了屬性依然報錯
任意屬性使用 [propName: string]: any
(當然這里這個屬性限制為了字符串)
interface Person {
name: string,
age?: number,
[propName: string]: any
}
let james: Person {
name: 'james'
age: 27,
job: 'bricks diliver'
} // ok
只讀屬性使用 readonly
: 只讀的約束在于第一次給對象賦值的時候熬芜,而不是第一次給只讀屬性賦值的時候
interface Person {
readonly id: number,
name: string,
age?: number,
[propName: any]: any;
}
let james: Person = {
id: 10086, // 初始化賦值
name: 'james'
} // ok
james.id = 10010; // 錯誤,只讀屬性不能賦值
二.數(shù)組和類數(shù)組
數(shù)組的表示方式有以下幾種:
// 普通形
let arr: number[] = [1, 2, 3]
let arr: (number | string)[] = [1, 'james']
// 泛型 Array<elemType>
let genericArr: Array<number> = [1, 2, 3]
// 使用接口描述數(shù)組
interface NumberArr {
[index: number]: number // 表示只要 'index' 的類型是 number, 那么值的類型必須是 number
}
let someNumArr: NumberArr = [1, 2, 3]
類數(shù)組不是數(shù)組類型,一般類數(shù)組都有自己的接口類型无切,如 IArguments
, NodeList
, HTMLCollection
等等
function sum() {
let args: IArguments = arguments;
}
三.函數(shù)類型
一般寫法:
// 寫法1
function sum(a: number, b: number): number {
return a + b;
}
// 傳入的參數(shù)過少或過多或類型不符都會報錯
sum(10) // error
sum(10, 20, 30) // error
let sum = function(a: number, b: number): number {
return a + b;
}
函數(shù)表達式
let mySum: (a: number, b: number) => number = function(a: number, b: number): number {
return a + b;
}
// 或
let mySum: (a: number, b: number) => number = function(a, b) {
return a + b;
}
在typescript中 =>
用來表示函數(shù)的定義,左邊是輸入類型丐枉, 右邊是輸出類型哆键。注意這點和ES6的箭頭表達式的區(qū)別
參數(shù)默認值
ES6中可以直接寫默認值,ts寫法為:
function getFullName(firstName: string, lastName: string = 'William'): string {
return firstName + ' ' + lastName;
}
rest操作符 ...
ES6語法類似:
function push(arr: any[], ...items: any[]) {
items.forEach(function(item) {
arr.push(item);
});
}
let a = [];
push(a, 1, 2, 3);
函數(shù)重載
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('');
}
}
這樣寫有一個缺點矛洞,就是表達不夠精確洼哎,輸入為數(shù)字的時候,輸出也應(yīng)該為數(shù)字沼本,輸入為字符串的時候噩峦,輸出也應(yīng)該為字符串。
下面是重載的寫法:
// Typescript會優(yōu)先從最前面的函數(shù)定義開始匹配
// 所以多個函數(shù)定義如果由包含關(guān)系抽兆,需要優(yōu)先把精確的定義寫在前面识补。
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('');
}
}
四.類型斷言 Type Assertion
類型斷言用于繞過編譯器的類型推斷,手動指定一個值的類型
語法:
<Type>variable
// 或
value as type (React的JSX語法只能使用這種)
例子: 比如將一個聯(lián)合類型的變量指定為一個更加具體的類型
當TypeScript不確定一個聯(lián)合類型
的變量到底是哪個類型時辫红, 我們只能訪問聯(lián)合類型的公共方法和屬性
function getLength(something: string | number): number {
return something.length;
} // 報錯凭涂,number類型不存在length屬性
而有時候確實需要在還不確定類型的時候就訪問其中一個類型的屬性或方法祝辣,比如:
function getLength(something: string | number): number {
if (something.length) {
return something.length;
} else {
return something.toString().length;
}
} // 報錯 number類型不存在length屬性
這個時候我們可以使用類型斷言,將'something' 斷言為 'string'
function getLength(something: string | number): number {
if ((<string>something).length) { // (<string>something)
return (<string>something).length;
} else {
return something.toString().length;
}
}
// 或
function getLength(something: string | number): number {
if ((something as string).length) { // (<string>something)
return (something as string).length;
} else {
return something.toString().length;
}
}
類型斷言不是類型轉(zhuǎn)換切油,斷言為一個不存在的類型是會報錯的
function toBoolean(something: string | number): number {
return <boolean> somethins;
} // 錯誤 Type 'string | number' cannot be converted to type 'boolean'
五.聲明文件
當使用第3方庫的時候蝙斜,我們需要引用它的聲明文件
比如想引入jQuery
$('#name')
// 或
jQuery('#name')
但是TypeScript中,并不知道 $
或jQuery
是什么東西澎胡,直接使用會報錯
我們需要使用 declare
關(guān)鍵字來定義它:
// declare 定義的類型只會用于編譯時的檢查孕荠,編譯結(jié)果中會被刪除。
declare var jQuery: (string) => any;
jQuery('#foo') // ok
聲明文件
通常我們會把類型聲明放到一個單獨的文件中攻谁, 約定文件以 .d.ts
為后綴:
// jQuery.d.ts
declare var jQuery: (string) => any;
然后在使用到的文件的開頭稚伍,用 ///
表示引入文件
/// <reference path="./jQuery.d.ts" />
jQuery('#name');
第3方聲明文件
當然jQuery已經(jīng)有第三方幫我們定義好了,我們可以直接安裝使用戚宦, TypeScript推薦使用 @types
來管理
@types
的使用方式也很簡單:
npm install @types/jQuery --save-dev
可以使用 TypeSearch來搜索需要的聲明文件
六.內(nèi)置對象
TypeScript內(nèi)置定義很多都定義在TypeScript核心庫中
ECMAScript 內(nèi)置對象 Boolean
, Error
, Date
, RegExp
等
let b: Boolean = new Boolean(1)
let r: RegExp = /[a-z]/
DOM, BOM內(nèi)置對象:Document
, HTMLElement
, Event
, NodeList
*等
let body: HTMLElement = document.body;
let allDiv: NodeList = document.querySelectorAll('div');
document.addEventListener('click', function(e: MouseEvent)) {
// ...
}
用TypeScript寫Node.js
Node.js不是內(nèi)置對象的一部分个曙, 如果想要用Typescript寫,則需要引入第三方聲明
npm i -D @types/node
總結(jié)
TypeScript的寫法對于有后端基礎(chǔ)的應(yīng)該很熟悉受楼,這里只是做基本的概念介紹垦搬。對我而言,斷言和聲明文件部分比較陌生那槽,另外第三方聲明文件的方式也比較陌生悼沿。