一. 概覽
本文詳細介紹泛型中泛型對象和泛型類的使用,結合實際應用場景,加深對泛型的理解、使用。
二. 泛型對象
舉個例子
const test = {a: 1,b: 1
}
一個類型有沒有一種可能讓我么在定義的時候傳入一個類似于變量的形參,在使用的時候傳入具體的類型參數。在定義前不知道具體的參數類型
當然我們也可以定義為any,但是和沒有限制差別不大
引入泛型對象
interface ITest<T> {id: Number,content: T,completed: boolean
}const test:ITest<string> = {id: 1,content: '',completed: true
}
泛型實參會限制泛型形參變量的類型
作為函數的形參和實參
function createTodo<T>({id,content,completed
}: ITest<T>) {return {id,content,completed}
}const todo1 = createTodo<string[]>({id:2, content: ['唱','跳','rap'],completed:true})
三. 泛型類
在class中,所以屬性都應該是私有的,如果需要獲取屬性,設置屬性都應該由公共的getter setter方法去完成。
完整代碼
interface ITodoProps<T> {id: number,content: T;completed: boolean
}interface ITodo<T> {get(): ITodoProps<T>,create():string
}class Todo<T> implements ITodo<T>{private id: number;private content: T;private completed: boolean;constructor(id: number, content: T, completed: boolean) {this.id = id;this.content = content;this.completed = completed;}get(): ITodoProps<T> {return {id: this.id,content: this.content,completed: this.completed}}create(): string {if (typeof this.content === "string") {return this.createStringContent(this.content);} else if (Array.isArray(this.content) && typeof this.content[0] === "string") {return this.createArrayContent(this.content as string[]);} else {return this.createObjectContent(this.content);}}private createStringContent(content: string): string {return content}private createArrayContent(content: string[]): string {return content.join(',')}private createObjectContent(content: T): string {let _content = '';for (let key in content) {let _content = "";_content += `${key}: ${content[key]}`}return _content}
}const todo11 = new Todo<string[]>(2,['逛街','打球','看電影'],false)const todo12= new Todo<{[key:string]:number}>(3, {sleep:1,walking:2,study:3},false)const todoString111 =todo11.create()const todoString112=todo12.create()const todoList = [todoString111,todoString112]const todo1 = todo11.get()const todo2 = todo12.get()function getTodoProp<T, K extends keyof T>(todo: T,key: K) {return todo[key]}getTodoProp(todo1,'id')
可以結合例子,去看泛型類的使用
keyof的使用
function getTodoProp<T, K extends keyof T>(todo: T,key: K) {return todo[key]}getTodoProp(todo1,'id')
疑問:getTodoProp(todo1,‘id’)為什么可以編譯成功,不需要傳T的具體類型嗎?
解答:
- getTodoProp 函數使用了泛型和 TypeScript 的索引類型查詢,可以在不使用 T 類型的情況下獲取 todo 對象上的 key 屬性對應的值。
- 在函數定義中,泛型類型參數 T 表示傳入的 todo 參數的類型,而泛型類型參數 K 是具有約束條件 extends keyof T 的索引類型查詢,表示必須是 T 對象的屬性名之一。
當我們在調用 getTodoProp 函數時,傳入了一個 todo1 對象作為 todo 參數,而 TypeScript 會根據該對象的類型自動推斷 T 類型為:
{
id: number;
content: string;
}
在 getTodoProp(todo1, ‘id’) 調用中,K 類型被推斷為 ‘id’,因此 key 參數的類型為 ‘id’,這個類型也符合泛型類型參數 K 的約束條件。
類似地
function getSplitValue3<E>(value: E[],type: string):string {return value.join(type)
}const aa = getSplitValue3<string>(['a','b','c'],',')
const bb = getSplitValue3<number>([1,2,3],',')
可以省略為
function getSplitValue3<E>(value: E[],type: string):string {return value.join(type)
}const aa = getSplitValue3(['a','b','c'],',')
const bb = getSplitValue3([1,2,3],',')