一. 資料型別
變數可以使用資料型別修飾, 限制了變數別隨意賦值帶來的不可預測性
let age: number = 12;
let isDone: boolean = false;
let myName: string = 'Tom';
let unusable: void = undefined;
let u: undefined = undefined;
let n: null = null;
複製程式碼
有的時候資料型別是不可預測的, 有的場景下, 也是需要可以接受任意型別的變數. 這時候就可以使用任意值
let anyThing: any = 'hello';
anyThing = 3;
複製程式碼
型別推斷
- 在宣告時,給定了值, 那麼變數就會被推斷對應的型別.
let myFavoriteNumber = 'seven'; // let myFavoriteNumber: string = 'seven';
myFavoriteNumber = 7;
複製程式碼
- 如果定義的時候沒有賦值,不管之後有沒有賦值,都會被推斷成 any 型別而完全不被型別檢查:
let something; // let something: any;
something = 'seven';
something = 7;
something.setName('Tom');
複製程式碼
聯合型別
- 一個型別可以同時指定多個型別
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
複製程式碼
當使用聯合型別時, 變數只能使用兩個型別中公共的方法和屬性.
- 如果是我們需要在方法中根據型別呼叫特定的方法時, 就需要使用
斷言
語法.斷言
只能從聯合型別中選取型別
複製程式碼
物件型別---介面
程式開發有一個很流行的模式,就是面向介面程式設計. 介面抽象了結構, 真正的實現就可以提供多種多樣的能力.
interface Person {
name: string; // name是確定屬性, 實現介面的物件,必須失效該屬性
age?: number; // age是可選屬性, 也就是真正實現時,不需一定實現.
readonly id: number; // 只讀屬性,
}
let tom: Person = {
name: 'Tom',
age: 25,
id: 100, // 只能在物件賦值時設定值.
};
複製程式碼
陣列的型別
let fibonacci: number[] = [1, 1, 2, 3, 5];
// 報錯, 陣列中只允許單一型別
let fibonacci2: number[] = [1, '1', 2, 3, 5];
// 泛型陣列
let fibonacci: Array<number> = [1, 1, 2, 3, 5];
// 介面型別陣列
interface NumberArray {
[index: number]: number;
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];
// 要求陣列中存放不同型別的值
let list: any[] = ['Xcat Liu', 25, { website: 'http://xcatliu.com' }];
複製程式碼
函式的型別
- 注意,輸入多餘的(或者少於要求的)引數,是不被允許的:
function sum(x: number, y: number): number {
return x + y;
}
sum(1, 2); // 正常
sum(1, 2, 3);// 多輸入一個引數, 會報錯
複製程式碼
- 使用可選引數, 可以省略引數的輸入, 可選引數一定要在引數列表的尾部.
function buildName(firstName: string, lastName?: string) {
if (lastName) {
return firstName + ' ' + lastName;
} else {
return firstName;
}
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');
複製程式碼
- 用介面定義函式的型別
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
return source.search(subString) !== -1;
}
複製程式碼
宣告檔案: declare
我們需要使用 declare
關鍵字來定義它的型別,幫助 TypeScript 判斷我們傳入的引數型別對不對:
declare var jQuery: (selector: string) => any;
jQuery('#foo');
複製程式碼
注意:
-
通常宣告檔案放到一個單獨的檔案中管理. 例如:
jQuery.d.ts
-
用「三斜線指令」表示引用了宣告檔案,
/// <reference path="./jQuery.d.ts" />
-
第三方宣告檔案,
npm install @types/jquery --save-dev
Node
Node.js 不是內建物件的一部分,如果想用 TypeScript 寫 Node.js,則需要引入第三方宣告檔案:
npm install @types/node --save-dev
複製程式碼
二. 進階用法
關鍵字: type
型別別名
例如定義一個函式的型別, 引數型別加上返回值型別, 導致型別描述很長, 這時候就可以使用型別別名簡化.
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
if (typeof n === 'string') {
return n;
}
else {
return n();
}
}
複製程式碼
字串字面量型別
作為型別時, 引數只能是約定好的內容. 類似於列舉
type EventNames = 'click' | 'scroll' | 'mousemove';
function handleEvent(ele: Element, event: EventNames) {
// do something
}
handleEvent(document.getElementById('hello'), 'scroll'); // 沒問題
handleEvent(document.getElementById('world'), 'dbclick'); // 報錯,event 不能為 'dbclick'
複製程式碼
元祖
陣列: 相同元素集合,
元祖: 不同元素集合
let xcatliu: [string, number];
xcatliu[0] = 'Xcat Liu';
xcatliu[1] = 25;
xcatliu[0].slice(1);
xcatliu[1].toFixed(2);
// 報錯, 型別不一致
let k: [string, number] = [18,'Tom', 18]
複製程式碼
注意:
- 元素的定義時的位置是固定的.
[18,'Tom', 18]
的型別就是[number, string, number]
- 對應位置可以使用該位置型別的方法,
- 如果在元祖中
push
- 額外元素的型別為元祖中元素的聯合型別
number | string
關鍵字: enum
一般列舉
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
複製程式碼
編譯後
var Days;
(function (Days) {
Days[Days["Sun"] = 0] = "Sun";
Days[Days["Mon"] = 1] = "Mon";
Days[Days["Tue"] = 2] = "Tue";
Days[Days["Wed"] = 3] = "Wed";
Days[Days["Thu"] = 4] = "Thu";
Days[Days["Fri"] = 5] = "Fri";
Days[Days["Sat"] = 6] = "Sat";
})(Days || (Days = {}));
;
複製程式碼
- 它的預設值,如下每個較前一個
+ 1
console.log(Days["Sun"] === 0); // true
console.log(Days["Mon"] === 1); // true
console.log(Days[2] === "Tue"); // true
console.log(Days[6] === "Sat"); // true
複製程式碼
- 手動賦值, 以最後面的數值遞增.
enum Days {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat};
console.log(Days["Sun"] === 7); // true
console.log(Days["Mon"] === 1); // true
console.log(Days["Tue"] === 2); // true
console.log(Days["Sat"] === 6); // true
複製程式碼
常數列舉
每一項的內容是常數, 不可計算得到.
const enum Directions {
Up,
Down,
Left,
Right
}
let dir: Directions = Directions.Up
複製程式碼
編譯後
var dir = 0 /* Up */;
複製程式碼
外部列舉
// 此處必須使用const, 不然declare 定義的型別只會用於編譯時的檢查,編譯結果中會被刪除。
declare const enum Directions {
Up,
Down,
Left,
Right
}
let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];
複製程式碼
編譯結果:
var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];
複製程式碼
三. 類的使用
訪問修飾符
- public : 任何地方都可以被訪問, 預設的屬性和方法都是
publick
- private: 只有當前類可以訪問.
- protected: 和
private
類似, 但可以被子類訪問.
抽象類
abstract
用於定義抽象類和其中的抽象方法.
使用關鍵字 extends
繼承抽象類
注意:
- 抽象類不能被例項化
- 抽象方法必須被子類實現
介面
介面可以描述一個物件屬性, 同時可以對行為
進行抽象
- 使用關鍵字
implements
實現介面 - 一個類可以實現多個介面
- 介面之間可以是繼承關係
interface Alarm {
alert();
}
interface Light {
lightOn();
lightOff();
}
interface FlyableAlarm extends Alarm{
fly();
}
class Door {
}
class SecurityDoor extends Door implements Alarm {
alert() {
console.log('SecurityDoor alert');
}
}
class Car implements Alarm, Light {
alert() {
console.log('Car alert');
}
lightOn() {
console.log('Car light on');
}
lightOff() {
console.log('Car light off');
}
}
class Plane implements FlyableAlarm{
alert(){
console.log('Plane alert');
}
fly(){
console.log('Plane fly');
}
}
複製程式碼
- 介面繼承類
class Point {
x: number;
y: number;
}
interface Point3d extends Point {
z: number;
}
let point3d: Point3d = {x: 1, y: 2, z: 3};
複製程式碼
泛型
定義函式,介面或類的時候, 不預先指定具體的型別, 而在使用的時候再指定型別的一種特性
- 函式使用泛型
function createArray<T,N extends number>(length: N, value: T): Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
createArray<string>(3, 'x'); // ['x', 'x', 'x']
複製程式碼
- 介面使用泛型
interface CreateArrayFunc {
<T>(length: number, value: T): Array<T>;
}
// 也可以把泛型提升到介面名上
//interface CreateArrayFunc<T> {
// (length: number, value: T): Array<T>;
//}
let createArray: CreateArrayFunc;
createArray = function<T>(length: number, value: T): Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
createArray(3, 'x'); // ['x', 'x', 'x']
複製程式碼
- 類使用泛型
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; };
複製程式碼
- 指定泛型的預設型別
function createArray<T = string>(length: number, value: T): Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
複製程式碼
原文連線: https://ts.xcatliu.com/