TypeScript——泛型

泛型

TS中可以使用泛型創建可重用的組件,一個組件可以支持多種類型的數據,這樣用戶就可以以自己的數據類型來使用組件。

泛型變量

通過泛型變量,可以知道用戶傳入的類型,從而可以以這個類型作爲函數的返回類型。

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

當然也可以直接通過類型推斷

let res = identity('hello world') // 編譯時,類型推斷則會推斷這個數據類型爲 string

值得注意的是,對於泛型變量,它是可以代表任意類型的,如果不指定泛型變量的類型,就在函數中操作指定的類型變量所具有的方法,就會報錯。
例如:

function identity<T>(arg: T): T {
	console.log(arr.length)
	return arg  // 此時會報錯,T並沒有length這個屬性
}

解決方法

function identity<T>(arg: T[]): T[] {
	console.log(arr.length)// 此時就不會報錯,因爲T[]可以代表任意數據類型的數組
	return arg
}

也可以這樣實現

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

此時這個泛型就代表任意數據類型的數組

泛型接口

  1. 常見的使用方式
interface GenericIdentityFn {
	<T>(arg: T): T
}

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

let myIdentity: GenericIdentityFn = identity

相當於

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

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

即把 {(arg: T): T} 定義成一個接口使用

  1. 將泛型參數當作整個接口的一個參數使用
interface GenericIdentityFn<T> {
	(arg: T): T
}
function identity<T>(arg: T): T {
	return arg
}

let myIdentity: GenericIdentityFn<number> = identity

泛型類

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 }

需要注意的是,泛型類限制的只是類的實例部分的類型,對於靜態部分不能使用泛型類。

泛型約束

泛型約束顧名思義在泛型的前提下加上一定的約束條件。
例如:

interface Lengthwise {
	length: number
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
	console.log(arg.length)
	return arg
}

loggingIdentity(3) // 報錯 3是number類型,並具有length這個屬性
loggingIdentity({length: 3, value: 3 }) // 不會報錯,因爲傳入的變量具有length這個屬性
  1. 在泛型約束中使用類型參數
function getProperty(obj: T, key: K) {
	return obj[key]
}

let x = { a: 1, b: 2, c: 3, d: 4 }

getProperty(x, "a") // 成功
getProperty(x, "m") // 報錯  因爲x這個對象上沒有m這個屬性

這段代碼就是通過類型約束,將Key規定爲必須在obj上,即可以理解爲這個對象上的屬性

  1. 在泛型裏使用類類型
class BeeKeeper {
	hasMask: boolean
}

class ZooKeeper {
	nametag: string
}

class Animal {
	numLegs: number
}

class Bee extends Animal {
	keeper: BeeKeeper
}

class Lio extends Animal {
	keeper: Zookeeper
}

function createInstance<A extends Animal>(c: new () => A): A {
	return new c()
}

createInstance(Lio).keeper.nametag
createInstance(Bee).keeper.hasMask
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章