一、定義
比如我們有一個函式,如果不使用範型是這樣的
function getData(arg: number): number {
return arg;
}
複製程式碼
它只能傳入number型別,如果我們要傳入一個string型別的是編譯不通過的,所以我們可以寫另一個函式或者用any型別
function getData1(arg: string): string {
return arg;
}
function getData2(arg: any): any {
return arg;
}
複製程式碼
那麼問題來了,如果重新寫那麼我們就不能做到複用了,如果用any就不能保證傳進去的型別和傳出來的型別統一,所以我們有了範型
function getData<T>(arg: T): T {
return arg;
}
getData<number>(123)
getData<string>(123)
getData(false)//利用了型別推論,編譯器會根據傳入的引數自動地幫助我們確定T的型別
複製程式碼
T:表示範型,具體什麼型別是呼叫的這個方法的時候決定的(注意:T也可以是任意其他字母) 所以範型可以支援不確定的資料型別,傳入的引數和返回值的型別一致。
二、範型變數
如果我們想列印一個陣列的長度
function getLength<T>(arg: T): T {
console.log(arg.length); // Error: T doesn't have .length
return arg;
}
複製程式碼
如果這麼做,編譯器會報錯說我們使用了arg的.length屬性,但是沒有地方指明arg具有這個屬性。 記住,這些型別變數代表的是任意型別,所以使用這個函式的人可能傳入的是個數字,而數字是沒有.length屬性的。
現在假設我們想操作T型別的陣列而不直接是T。由於我們操作的是陣列,所以.length屬性是應該存在的。 我們可以像建立其它陣列一樣建立這個陣列:
function getLength<T>(arg: T[]): T[] {
console.log(arg.length); // Array has a .length, so no more error
return arg;
}
複製程式碼
三、範型類
泛型類使用(<>)括起泛型型別,跟在類名後面。
class Minclass<T> {
public list: T[] = []
add(value: T):void {
this.list.push(value)
}
min():T{
let minNum = this.list[0]
for(let i =0; i < this.list.length; i++){
if(minNum > this.list[i]){
minNum = this.list[i]
}
}
return minNum
}
}
let m = new Minclass<number>()
m.add(2)
m.add(6)
m.min() //2
let s = new Minclass<string>()
s.add('m')
s.add('c')
s.min()//c
複製程式碼
四、範型介面
interface ConfigFn{
<T>(value:T):T
}
let getData:ConfigFn = function<T>(value:T):T{
return value
}
複製程式碼
通用範型介面:
function getData<T>(value:T):T{
return value
}
interface ConfigFn<T>{
(value:T):T
}
let getData:ConfigFn<string> = getData
let getData1:ConfigFn<number> = getData
複製程式碼
五、在泛型約束中使用型別引數
class User{
username: string
password: string
}
class Mysql{
add (user:User):boolean{
console.log(user)
return true
}
}
let u = new User()
u.username = '張三'
u.password = '123'
let m = new Mysql()
m.add(u)
複製程式碼
我們可以通過範型約束來更好的實現上面的程式碼
class Mysql<T>{
add(info:T):boolean{
console.log(Info)
return true
}
}
let u = new User()
u.username = '張三'
u.password = '123'
let my = new Mysql<User>()
my.add(u)
複製程式碼