ts筆記-類型系統

在ts中,類型系統被設計爲可選的,因此可以認爲js就是沒有類型聲明的ts。

類型註解使用 :TypeAnnotation 語法

原始類型

let num: number;
let str: string;
let bool: boolean;

:number:string:boolean都是原始類型

數組

原始類型和[]結合,就是數組類型,如:number[]:string[]:boolean[]

let boolArray: boolean[];

boolArray = [true, false];

let strArray: string[];
strArray = ['1', '2'];


let numArray: number[];
numArray = [1,2]

內聯類型

內聯類型和數組類型有點像,數組是:typeAnnotation[],內聯是:{ /* Structure */}

let name: {
  first: string;
  second: string;
};

name = {
  first: 'John',
  second: 'Doe'
};

內聯類型能爲我們快速提供類型註釋。如果需要多次使用相同的內聯註解時,可以使用下面要說的接口。

接口

接口是ts類型系統的核心,這裏先做簡單介紹。接口可以認爲是把多個類型合併爲一個新的類型。


interface name {
  first: string;
  second: string;
}

let name1:name = {
  first: 'a',
  second: 'b'
}

let name2:name = {
  first: 'aa',
  second: 'bb'
}

特殊類型

特殊類型包括anynullundefined 以及 void

當我們把類型定義爲any,等同於關閉了ts類型檢查,因此任何類型都能賦予給他。在把js遷移到ts的時候,經常會使用到他。但過多的使用any就失去了類型檢查的意義,因此應該減少使用。

let power: any;

// 賦值任意類型
power = '123';
power = 123;

除了any類型,null和undefined也可以賦值給任意類型

// "strictNullChecks": false, 該值默認爲true

let num: number;
let str: string;

// 這些類型能被賦予
num = null;
str = undefined;

void類型

:void表示函數沒有返回值。

function log(message: string): void {
  console.log(message);
}

泛型

在說泛型前,讓我們先看一個實際的場景:假設有個函數,它接收一個列表,並且返回這個列表的反向排序。

function reverse(items) {
  const toreturn = [];
  for (let i = items.length - 1; i >= 0; i--) {
    toreturn.push(items[i]);
  }
  return toreturn;
}


let reversed = reverse([1,2,3]); // [3,2,1]

let reversed1 = reverse(['1', '2', '3']); // ['3', '2', '1']

如果沒有泛型,爲上面的函數添加類型就比較困難(當然也可以用聯合類型),因爲輸入的列表項可能是字符串、數字或者其他類型。使用泛型可以輕鬆解決。

function reverse<T>(items: T[]): T[] {
  const toreturn = [];
  for (let i = items.length - 1; i >= 0; i--) {
    toreturn.push(items[i]);
  }
  return toreturn;
}

泛型用<T>表示,T可以是任意字符。reverse函數接受類型爲T的數組,數組的每一項類型爲T,數組的返回值類型爲T。當我們傳入[1, 2, 3] 時,TypeScript 能推斷出 reverse 爲 number[] 類型,從而能給你類型安全。與此相似,傳入['1', '2', '3'] 時,TypeScript 能推斷 reverse 爲 string[] 類型

聯合類型

聯合類型用|表示,顧名思義,他可以表示多種不同的類型。

function formatCommandline(command: string[] | string) {
  let line = '';
  if (typeof command === 'string') {
    line = command.trim();
  } else {
    line = command.join(' ').trim();
  }
}

上面的函數即可以接收數組也可以接收字符串。

交叉類型

交叉類型是將多個類型合併爲一個類型,支持所有的類型。交叉類型用&表示,A & B 表示同時包含 A 和 B 的結果

interface Admin {
  id: number,
  administrator: string,
  timestamp: string
}

interface User {
  id: number,
  groups: number[],
  createLog: (id: number) => void,
  timestamp: number
}

let t: Admin & User

t!.administrator // 合法 Admin.administrator: string
t!.groups        // 合法 User.groups: number[]
t!.id            // 合法 id: number
t!.timestamp     // 合法 timestamp: never,never表示不允許被賦值

交叉類型 Admin & User 包含了原類型的所有屬性,但是要注意兩個接口都擁有 id 和 timestamp 屬性,且 id 類型相同,timestamp 類型不同。在此交叉類型中,timestamp 屬性類型衝突,不可被賦值。

一個實際的使用場景,mixins函數


function extend<T, U>(first: T, second: U): T & U {
  for(const key in second) {
    (first as T & U)[key] = second[key] as any
  }
  return first as T & U
}

var x = extend({ a: 'hello' }, { b: 42 });

元組類型

元組類型用於約束數組中的子項,使用:[typeofmember1, typeofmember2]表示

const nameAndNumber: [string, number];

nameAndNumber = ['wmui', 18]

類型別名

類型別名可以讓我們給類型起一個別名,在聯合類型和交叉類型中比較實用,使用type SomeName = someValidTypeAnnotation來創建

type text = string | { text: string };
type coordinates = [number, number];
type callback = (data: string) => void;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章