typescript 中的泛型
- 泛型的定義
- 泛型函數(shù)
- 泛型類
- 泛型接口
泛型:軟件工程中灸拍,我們不僅要創(chuàng)建一致的定義良好的API做祝,同時也要考慮可重用性。組件不僅能夠支持當前的數(shù)據(jù)類型鸡岗,同時也能支持未來的數(shù)據(jù)類型混槐,這在創(chuàng)建大型系統(tǒng)是為你提供了十分靈活的功能
在像 C# 和 java 這樣的語言中,可以使用泛型來創(chuàng)建可重用的組件轩性,一個組件可以支持多種類型的數(shù)據(jù)声登。這樣用戶就可以以自己的數(shù)據(jù)類型來使用組件
通俗的講:泛型就是解決 類 接口 方法 的復(fù)用性、以及對不特定數(shù)據(jù)類型的支持
泛型的定義
// 只能返回 string 類型的數(shù)據(jù)
function getData(value:string):string{
return value
}
// 傳入什么類型,就返回什么類型
// 泛型: 可以支持不特定的數(shù)據(jù)類型
// T 表示泛型,具體什么類型是調(diào)用方法是決定的
function getData<T>(value:T):T{
return value
}
getData<number>('123') // ×
getData<number>(123) // √
泛型類
// 泛型類: 比如有個最小堆算法,需要同時支持返回數(shù)字和字符串兩種類型,通過類的泛型來實現(xiàn)
class MinClass{
public list:number[] = []
add(num:number){
this.list.push(num)
}
min():number{
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()
m.add(2)
m.add(3)
m.add(1)
alert(m.min())
類的泛型
// 類的泛型
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(3)
m.add(1)
alert(m.min())
函數(shù)類型接口
/** 函數(shù)類型接口 規(guī)范 */
interface ConfigFn{
(value1:string,value2:string):string
}
let setData:ConfigFn = function(value1:string,value2:string):string{
return value1 + value2
}
setData("name","張三")
// 泛型接口
interface ConfigFn{
<T>(value1:T,value2:T):T
}
let setData:ConfigFn = function<T>(value1:T,value2:T):T{
return value1 + value2
}
setData<string>("name","張三")
//----------------------------------------
interface ConfigFn<T>{
(value1:T,value2:T):T
}
function getData<T>(value1:T,value2:T):T{
return value1 + value2
}
let myGetData:ConfigFn<string> = getData
myGetData("name","張三")
需求:定義一個操作數(shù)據(jù)庫的庫 支持 Mysql Mssql MongoDb
- 要求1: Mysql Mssql MongoDb 功能一樣揣苏,都有 add update delete get 方法
- 注意:約束統(tǒng)一的規(guī)范悯嗓、以及代碼重用
- 解決方案:需要約束規(guī)范所以要定義接口卸察,需要代碼重用所以用到泛型
- 接口:在面向?qū)ο蟮木幊讨猩鹱鳎涌谑且?guī)范的定義,它定義了行為和動作的規(guī)范
- 泛型:通俗的理解蛾派,泛型就是解決 類 接口 方法 的復(fù)用性
interface DBI<T>{
add(info:T):boolean
update(info:T,id:number):boolean
delete(id:number):boolean
get(id:number):any[]
}
//定義一個操作mysql數(shù)據(jù)庫的類
class MysqlDb<T> implements DBI<T>{
add(info:T):boolean{
}
update(info:T,id:number):boolean{
}
delete(id:number):boolean{
}
get(id:number):any[]{
}
}
//定義一個操作mssql數(shù)據(jù)庫的類
class MssqlDb<T> implements DBI<T>{
add(info:T):boolean{
}
update(info:T,id:number):boolean{
}
delete(id:number):boolean{
}
get(id:number):any[]{
}
}
// 操作用戶表: 定義一個User類和數(shù)據(jù)庫表做映射
class User{
username:string | undefined
password:string | undefined
}
let u = new User()
u.username = '張三'
u.password = '123456'
let mysql = new MysqlDb<User>() // 類作為參數(shù)來約束數(shù)據(jù)的類型
mysql.add(u)
ts模塊
內(nèi)部模塊:命名空間
外部模塊:模塊
// db.ts
export function getData():any[]{
return '數(shù)據(jù)'
}
// index.ts
import {getData} from './db'
// 命名空間 --> 避免命名重復(fù)
namespace A{ // 相當于私有的,需要暴露方法
//代碼
export class Dog{
name:string
constructor(name:string){
this.name = name
}
run(){
console.log(this.name + "是dog")
}
}
}
let d = new A.Dog("xxx")
d.run()
namespace B{
代碼
}
裝飾器
類裝飾器:在不修改類的情況下擴展類的功能
// 普通裝飾器 無參數(shù)
function logClass(params:any){
conaole.log(params)
// params 就是當前類
params.prototype.apiUrl = 'xxx'
}
@logClass
class HttpClient{
constructor(){
}
getData(){
}
}
let h:any = new HttpClient()
console.log(h.apiUrl)
/////----------------------------------/////
// 裝飾器工廠 可傳參
function logClass(params:string){
conaole.log(params)
return function(target:any){
console.log(target) // 當前類
console.log(params) // http://xxx
target.prototype.apiUrl = params
}
}
@logClass('http://xxx')
class HttpClient{
constructor(){
}
getData(){
}
}
let h:any = new HttpClient()
console.log(h.apiUrl)
屬性裝飾器
function logProperty(params:any){
return function(target:any,attr:any){
console.log(target) // 當前類
console.log(attr) // url
target[attr] = params
}
}
class HttpClient{
@logProperty('http://xxx')
public url:any | undefined
constructor(){
}
getData(){
}
}
let h:any = new HttpClient()
console.log(h.apiUrl)
方法裝飾器
function logMethod(params:any){
return function(target:any,methodName:any,desc:any){
console.log(target)
console.log(methodName)
console.log(desc)
console.log(desc.value)
target.apiUrl = 'xxx'
target.run = function(){
console.log('run')
}
let oMethod = desc.value
desc.value = function(...args:any[]){
args = args.map((value)=>{
return String(value)
})
conaole.log(args)
oMethod.apply(this,args)
}
}
}
class HttpClient{
@logProperty('http://xxx')
public url:any | undefined
constructor(){}
@logMethod("http://xxx")
getData(...args:any){
console.log('getData')
}
}
執(zhí)行順序
屬性裝飾器 => 方法裝飾器 => 方法參數(shù)裝飾器2 => 方法參數(shù)裝飾器1 => 類裝飾器2 => 類裝飾器1
同樣的裝飾器從后到前執(zhí)行
END