我的學習TS的總結, 主要參考官方文檔,對於其中不太容易理解的點進行剖析;寫下來,主要是本身爲了鞏固知識點,並給你們分享下,若有不對之處,請指出~javascript
另外,全部原始類型的字面量自己也可做爲類型使用,其外延只包括自身java
表示一個值能夠是幾種類型之一。 豎線(|)分隔;若一個值是聯合類型,只能訪問此聯合類型的全部類型裏共有的成員es6
將多個類型合併爲一個類型。 豎線(&)分隔;把現有的多種類型疊加到一塊兒成爲一種類型,它包含了所需的全部類型的特性,多用於mixinstypescript
從舊類型建立新類型的一種方式編程
type Readonly<T> = { readonly [P in keyof T]: T[P]; } type Partial<T> = { [P in keyof T]?: T[P]; } interface Person { name: string; age: number; } // 調用 type PersonPartial = Partial<Person>; type ReadonlyPerson = Readonly<Person>;
// 結果 interface PersonPartial { name?: string; age?: number; } interface PersonReadonly { readonly name: string; readonly age: number; }
一、用戶自定義類型保護:定義函數,返回類型謂詞(語法:parameterName is Type)
二、typeof類型保護:只有兩種形式能被識別: typeof v === "typename"和 typeof v !== "typename", "typename"必須是 "number", "string", "boolean"或 "symbol" 原始類型,若爲除前四個的其餘字符串,將不被識別爲類型保護
三、instanceof 類型保護:過構造函數來細化類型的一種方式。語法: 實例 instanceof 構造函數
數組
function pluck<T, K extends keyof T>(o: T, names: K[]): T[K][] { return names.map(n => o[n]); } interface Person { name: string; age: number; } let person: Person = { name: 'Jarid', age: 35 }; let strings: string[] = pluck(person, ['name']); // ok, ['Jarid]
其中
keyof T: 索引類型查詢操做符 (此實例中,爲person的屬性name、age,值等於'name'|'age')
K extends keyof T:泛型約束
T[K]: 索引訪問操做符(此實例中,爲person['name'])ide
定義類型有兩種方式: 接口(interface) 和類型別名(type alias), 它們的主要區別以下:函數
一、interface 只能定義對象類型或者函數, type 還能夠定義組合類型,交叉類型(&,相似並集),聯合類型(|,相似交集),原始類型
二、interface 方式能夠實現接口的 extends 和 implements , 而 type alias 則不行。
三、interface 能夠實現接口的合併,但 type alias 則不行。post
兼容能夠簡單理解能否賦值,A = B (A 兼容/包含 B)學習
一、Any最「寬」。兼容其它全部類型(換言之,其它類型都是Any的子類型) 二、Never最「窄」。不兼容任何其它類型 三、Void兼容Undefined和Null 四、其它類型都兼容Never和Void
例如:
type point1D = { x: number } // 父 A type point2D = { x: number, y: number } // 子 B A = B // ok
當且僅當類型 B 是 A 的子集時,A 兼容 B,B 能夠被當成 A 處理
A = B
參數:要求對應參數的類型兼容,數量容許多餘 (多的包含少的,即參數容許多,不準少) 返回值:類型兼容 (範圍更廣, 賦值變量是被賦值的變量的子類型)
能夠用來手動指定一個值的類型
語法:<類型>值
或 值 as 類型
(在 tsx 語法(React 的 jsx 語法的 ts 版)中必須用後一種。)
ECMAScript 內置對象: Error、RegExp、Date、Boolean 等
DOM/BOM 內置對象: Document、HTMLElement、Event、NodeList、MouseEvent 等
參考:
http://kbscript.com/2017/01/2...
https://juejin.im/post/5c2723...
泛型(Generics)是指在定義函數、接口或類的時候,不預先指定具體的類型,而在使用的時候再指定類型的一種特性。類型變量(類型參數) T
interface Lengthwise { length: number; } function loggingIdentity<T extends Lengthwise>(arg: T): T { console.log(arg.length); return arg; }
使用含有泛型的接口來定義函數形狀
interface ConfigFn{ <T>(value:T):T; } var getData:ConfigFn=function<T>(value:T):T{ return value; } getData<string>('張三'); getData<string>(1243); //錯誤
// 把類型參數提到接口名上 // 寫法一: interface ConfigFn<T>{ (value:T):T; } var getData:ConfigFn<string>=function<T>(value:T):T{ return value; } getData('20'); /*正確*/ // 寫法二: interface ConfigFn<T>{ (value:T):T; } function getData<T>(value:T):T{ return value; } var myGetData:ConfigFn<string>=getData; myGetData('20'); /*正確*/ myGetData(20) //錯誤
使用泛型來定義類
class GenericNumber<T> { zeroValue: T; add: (x: T, y: T) => T; } let myGenericNumber = new GenericNumber<number>(); myGenericNumber.zeroValue = 0; myGenericNumber.add = function(x, y) { return x + y; };
抽象類: abstract 修飾,裏面能夠沒有抽象方法。但有抽象方法(abstract method)的類必須聲明爲抽象類(abstract class)
一、抽象類是不容許被實例化的 二、抽象類中的抽象方法必須被子類實現,不能本身實現 三、可使用修飾符
注意:若是子類繼承的是一個抽象類,子類必須實現父類裏的抽象方法,否則的話不能實例化,會報錯。
類繼承類(class extends class)
類實現接口(class implements interface)
接口繼承接口(interface extends interface)
接口繼承類(interface extends class)
interface Counter { (start: number): string; interval: number; reset(): void; } function getCounter(): Counter { let counter = <Counter>function (start: number) { }; // 這裏有點疑問? counter.interval = 123; counter.reset = function () { }; return counter; } let c = getCounter(); c(10); c.reset(); c.interval = 5.0;
參考: https://ts.xcatliu.com/advanc...
接口的做用:在面向對象的編程中,接口是一種規範的定義,它定義了行爲和動做的規範;在程序設計裏面,接口起到一種限制和規範的做用。接口定義了某一批類所須要遵照的規範,接口不關心這些類的內部狀態數據,也不關心這些類裏方法的實現細節,它只規定這批類裏必須提供某些方法,提供這些方法的類就能夠知足實際須要。 typescrip中的接口相似於java,同時還增長了更靈活的接口類型,包括屬性、函數、可索引和類等。
面嚮對象語言:接口是對行爲和動做的抽象,而具體如何行動須要由類(classes)去實現(implement)
ts: 對類的部分行爲進行抽象,對對象的形狀進行描述; 把不一樣類中的共性抽取做爲接口,再由類分別去實現(implement)
簡而言之,定義規範標準,用於複用(與普通類型約束相比)。
interface Person { readonly id: number; // 只讀屬性 name: string; // 肯定屬性 age?: number; // 可選屬性 [propName: string]: string; // 任意屬性 [index: number]: string; // 可索引屬性 (name: string, age: number): void; // 函數 currentTime: Date; // 類類型的屬性 (類實現接口) setTime(d: Date); // 類類型的方法 }
注意:
一、使用 [propName: string] 定義了任意屬性取 string 類型的值。
須要注意的是,一旦定義了任意屬性,那麼肯定屬性和可選屬性的類型都必須是它的類型的子集
二、 只讀的約束存在於第一次給對象賦值的時候,而不是第一次給只讀屬性賦值的時候。給對象變量賦值後,只讀屬性不能再改變。
三、當一個類實現了一個接口時,只對其實例部分進行類型檢查。 constructor存在於類的靜態部分,因此不在檢查的範圍內
接口繼承接口
interface Shape5 { color: string; } interface Square5 extends Shape5 { sideLength: number; } let square = <Square5>{}; // 定義對象,使用斷言 console.log(square) // {} // let square:Square5 = {color: '', sideLength: 0} square.color = "blue"; square.sideLength = 10; console.log(square)
另:一個接口能夠繼承多個接口
接口繼承類
接口繼承類時,會繼承類的全部成員但不包含實現
class Person { type: string // ❗️這裏是類的描述 } interface Child extends Person { // ❗️Child 接口繼承自 Person 類,所以規範了 type 屬性 log(): void // 這裏其實有一個 type: string } // ⚠️ 上面的 Child 接口繼承了 Person 對 type 的描述,還定義了 Child 接口自己 log 的描述 // 🥇 第一種寫法 class Girl implements Child { type: 'child' // 接口繼承自 Person 的 log() {} // 接口自己規範的 } // 🥈 第二種寫法 class Boy extends Person implements Child { // 首先 extends 了 Person 類,而後還需知足 Child 接口的描述 type: 'child' log() {} }
當接口繼承了一個擁有私有(private)或受保護(protected)的成員的類時,這個接口類型只能被這個類或其子類所實現(implement)。
class Person { private type: string // ❗️這裏是類的描述 } interface Child extends Person { // ❗️Child 接口繼承自 Person 類,所以規範了 type 屬性 log(): void // 這裏其實有一個 type: string } // ⚠️ 上面的 Child 接口繼承了 Person 對 type 的描述,還定義了 Child 接口自己 log 的描述 // 寫法 (only) class Boy extends Person implements Child { // 首先 extends 了 Person 類,而後還需知足 Child 接口的描述 type: 'child' log() {} }
定義函數方式:
let mySum = function (x, y) { return x + y; };
一、函數聲明
function sum(x: number, y: number): number { return x + y; }
二、函數表達式
let mySum = function (x: number, y: number): number { return x + y; }; 或者 let mySum: (x: number, y: number) => number = function (x: number, y: number): number { return x + y; };
可選參數:(?:) 必須接在必需參數後面
參數默認值: 至關於可選參數,任意位置
剩餘參數:(...rest)必須是在最後,與 es6 相同
java中方法的重載:重載指的是兩個或者兩個以上同名函數,但它們的參數不同,這時會出現函數重載的狀況。
typescript中的重載:經過爲同一個函數提供多個函數類型定義,一個函數體實現多種功能的目的。
ts爲了兼容es5 以及 es6 重載的寫法和java中有區別。
重載:同名函數,參數不同。容許一個函數接受不一樣數量或類型的參數時,做出不一樣的處理
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(''); } }
父類定義一個方法不去實現,讓繼承它的子類去實現, 每個子類有不一樣的表現(用於繼承)
注意:使用多態基礎是類的繼承或者接口實現。
typescript中的抽象類:
一、它是提供其餘類繼承的基類,不能直接被實例化。
二、用abstract關鍵字定義抽象類和抽象方法,抽象類中的抽象方法不包含具體實現而且必須在派生類中實現。
三、abstract抽象方法只能放在抽象類裏面
用途:抽象類和抽象方法用來定義標準 。 (抽象類:Animal 這個類要求它的子類必須包含eat方法,不然報錯;多態:子類繼承父類,子類能夠不實現該方法,但使用多態就是子類爲了實現方法)
從ECMAScript 2015開始,JavaScript引入了模塊的概念。TypeScript沿用此概念,在TS 中,模塊分爲內部模塊和外部模塊,自typescript 1.5 後,內部模塊稱做「命名空間」,外部模塊稱做「模塊」
同Java的包、.Net的命名空間同樣,TypeScript的命名空間將代碼包裹起來,經過export關鍵字對外暴露須要在外部訪問的對象。
在代碼量較大的狀況下,爲了不各類變量命名相沖突,可將類似功能的函數、類、接口等放置到命名空間內
主要用於組織代碼,解決命名衝突,會在全局生成一個對象,定義在namespace內部的類都要經過這個對象的屬性訪問
主要是解決加載依賴關係的,側重代碼的複用。跟文件綁定在一塊兒,一個文件就是一個module,模塊寫法和ES6同樣
一、書寫一個全局變量的聲明文件(書寫一個全局變量的聲明文件時,若是須要引用另外一個庫的類型)
二、依賴一個全局變量的聲明文件
命名空間和模塊的區別: