iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 8
0
Modern Web

TypeScript 初學之路系列 第 8

Day08 - Generic(上)

泛型

泛型的 Hello world

function identity(arg: number): number {
    return arg;
}

或是我們用 any 來宣告型態

function identity(arg: any): any {
    return arg;
}

使用 any 導致這個函式可以接受任何類型的 arg 參數,但是這樣會錯失一些訊息

我們需要一種方式讓 input 和 output 類型是一樣的

function identity<T>(arg: T): T{
  return arg;
}

藉由前面輸入的 T 協助接到 input 也希望和 response 是相同的,是相同的

function identity<T>(arg: T): T{
  return arg;
}

let output = identity<string>("Mystring");

使用泛型變數

若是我們希望取回 arg 的長度但是並沒有指明 arg 具有 .length 這個屬性

因為這個變量是任意類型,所以傳入的可能是字串或數字

那就沒有 length 這個屬性

我們可以先宣告陣列

function loggingIdentity<T>(arg: T[]): T[]{
  console.log(arg.length);
  return arg;
}

現在 loggingIdentity 的輸入直是包含了 T 屬性的陣列

回傳的也是包含了 T 的陣列

也可以改寫成為

function loggingIdentity<T>(arg: Array<T>): Array<T> {
    console.log(arg.length);  // Array has a .length, so no more error
    return arg;
}

泛型 class

在函式忠宣告泛型的方式如下

function identity<T>(arg: T): T{
  return arg;
}

let myIdentity: <T>(arg: T) => T = identity;

也可以使用不同的名稱宣告,只要變數的數量吻合就可以了

function identity<T>(arg: T): T {
    return arg;
}

let myIdentity: <U>(arg: U) => U = identity;

也可以利用 signature 物件的方式來做宣告

function identity<T>(arg: T): T {
    return arg;
}

let myIdentity: {<T>(arg: T): T} = identity;

上述範例可以利用 interface 來做宣告

interface GenericIdentityFn{
  <T>(arg: <T>): T;
}
function identity<T>(arg: T): T{
  return arg;
}

let myIdentity: GenericIdentityFn = identity;

藉由上述範例使用泛型來做宣告的話

就可以把這個參數的型態作為函式的輸入值

例如: Dictionary而不是單純的 Dictionary

interface GenericIdentityFn<T> {
    (arg: T): T;
}

function identity<T>(arg: T): T {
    return arg;
}

let myIdentity: GenericIdentityFn<number> = identity;

泛型類別

泛型類別和泛型宣告方式是一樣的,利用 <> 在 class 後面

class GenericNumber<T>{
  zeroValue: T;
  add: (x: T, y: T) => T;
}

et myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };

GenericNumber 很片面的 class,沒什麼去限制他使用 number 你可以使用字串或其他更複雜的物件

let stringNumeric = new GenericNumber<string>();
stringNumeric.zeroValue = "";
stringNumeric.add = function(x, y) { return x + y; };

alert(stringNumeric.add(stringNumeric.zeroValue, "test"));

就像 interface 一樣

泛型類別只是確認你使用的是同一個型態

而什麼型態則不是他們限制的

在之前 類別中有提到

類別有分兩個部分 靜態與實例層

泛型類別只負責實例層 靜態層不能使用 泛型類別


上一篇
Day07 - Classes
下一篇
Day09 - JSX (上)
系列文
TypeScript 初學之路11

尚未有邦友留言

立即登入留言