typescript 中的泛型
- 泛型的定义
- 泛型函数
- 泛型类
- 泛型接口
-
泛型:软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统是为你提供了十分灵活的功能
-
在像 C# 和 java 这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件
-
通俗的讲:泛型就是解决 类 接口 方法 的复用性、以及对不特定数据类型的支持
泛型的定义
// 只能返回 string 类型的数据
function getData(value:string):string{
return value
}
// 传入什么类型,就返回什么类型
// 泛型: 可以支持不特定的数据类型
// T 表示泛型,具体什么类型是调用方法是决定的
function getData<T>(value:T):T{
return value
}
getData<number>('123') // ×
getData<number>(123) // √
泛型类
// 泛型类: 比如有个最小堆算法,需要同时支持返回数字和字符串两种类型,通过类的泛型来实现
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())
函数类型接口
/** 函数类型接口 规范 */
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","张三")
需求:定义一个操作数据库的库 支持 Mysql Mssql MongoDb
- 要求1: Mysql Mssql MongoDb 功能一样,都有 add update delete get 方法
- 注意:约束统一的规范、以及代码重用
- 解决方案:需要约束规范所以要定义接口,需要代码重用所以用到泛型
- 接口:在面向对象的编程中,接口是规范的定义,它定义了行为和动作的规范
- 泛型:通俗的理解,泛型就是解决 类 接口 方法 的复用性
interface DBI<T>{
add(info:T):boolean
update(info:T,id:number):boolean
delete(id:number):boolean
get(id:number):any[]
}
//定义一个操作mysql数据库的类
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数据库的类
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类和数据库表做映射
class User{
username:string | undefined
password:string | undefined
}
let u = new User()
u.username = '张三'
u.password = '123456'
let mysql = new MysqlDb<User>() // 类作为参数来约束数据的类型
mysql.add(u)
ts模块
内部模块:命名空间
外部模块:模块
// db.ts
export function getData():any[]{
return '数据'
}
// index.ts
import {getData} from './db'
// 命名空间 --> 避免命名重复
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{
代码
}
装饰器
类装饰器:在不修改类的情况下扩展类的功能
// 普通装饰器 无参数
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')
}
}
执行顺序
属性装饰器 => 方法装饰器 => 方法参数装饰器2 => 方法参数装饰器1 => 类装饰器2 => 类装饰器1
网友评论