typescript学习:Generics泛型

本文内容如下

泛型Generics的了解与使用

如果你都有了答案,可以忽略本文章,或去TS学习地图寻找更多答案


泛型

  • 定义:占位符,定义时不知道未来需要什么值,等调用的时候再传
  • 作用:提升类,接口,方法的复用性
  • 场景:封装
  • 组件/函数不仅考虑支持当前的数据类型,同时也能支持未来的数据类型
  • 注意:传入的参数和返回的参数一致

语法

<T>声明,用T占位,T是自己写的,可以是任意字符
占位地方:参数,返回值

function fn<T>(value1: T, value2: T): T {}

const fn = <T>(value:T):T => value

泛型函数

function getData<T>(value1: T, value2: T): void {
    console.log(value1, value2)
}
getData<number>(1, 2)              //正确
getData<string>('hello', 'ts')     //正确
getData<number>(1, '123')          //报错,存在字符串类型
getData<number | string>(1, '123') //正确,支持混合类型
getData('hi', 'react')             //正确,ts会帮做类型推论


多个参数,在返回值中可以规定顺序
function show<T, U>(tuple:[T, U]):[U, T]{
    return [tuple[1], tuple[0]]
}
show<string, number>(['string', 123]) //123, string

泛型接口

函数,第一种:
interface ConfigFn {
    <T>(value: T): T;
}
let getData: ConfigFn = (value) => value
getData<string>('张三')



函数,第二种:
interface ConfigFn<T>{
    (value:T):T;
}
function getData<T>(value:T):T{
    return value
}
let myGetData : ConfigFn<string> = getData
myGetData('abc')



多个泛型,需要按顺序填写
interface KeyPair<K, V> {
    key:K;
    value:V;
}
let kp1: KeyPair<number,string> = {key: 123, value: 'str'}
let kp2: KeyPair<string,number> = {key: 'str', value: 123 }



适配不同的函数
interface Iplus<T> {
    (a:T,b:T):T
}
function plus(a:number,b:number):number{
    return a + b
}
function connect(a:string,b:string):string{
    return a + b
}
const p : Iplus<number> = plus
const c : Iplus<sring> = connect

泛型类

例子1:实现队列功能
class Queue<T>{
    private data:T[] = []
	push(item:T):void{
        this.data.push(item)
    }
	pop():void{
        this.data.pop(item)
    }
}
const queue = new Queue<number>() //限制传入的是数字类型
queue.push(1)
queue.push('str') //报错,不是数字类型

const queue = new Queue<string>()  //限制传入的是字符串类型
queue.push('str')
log(queue.pop().length)  //字符串,可以使用字符串方法



例子2class MysqlDB<T> {
    add(info:T):boolean{
        return true
    }
}
class User {
    username:string | undefined;
	password:string | undefined;
}
let u = new User()
u.username = 'dashen'
u.password = '123456'

let myDB = new MysqlDB<User>() //传入类作为效验
myDB.add(u)

约束泛型

第一种:约束传入的参数是数组
function sayHi<T>(names: T[]){}  //写法一
function sayHi<T>(names: Array<T>){  //写法二
     console.log(arg.length)
     retrun arg
}
sayHi([1,2,3])
sayHi<string>(['tao','shen'])



第二种:使用extends
鸭子叫(像鸭子叫就行),不管是什么类型都可以,有length属性就行
interface IWithLength {
    length:number
}
function echoWithLength<T extends IWithLength >(arg:T):T {
    console.log(arg.length)
    retrun arg
}
const arr = echoWithLength([1,2,3])
const res = echoWithLength('str')  //可以传字符串,字符串有length
const obj = echoWithLength({length: 10})   //也可以传带length属性的对象

泛型类约束

// 参数约束:
// 1参:对象, 2参:该对象的key
class ObjectRef<O extends object, K extends keyof O> {
    constructor(private _object: O, private _key: K) { }

    get value() {
        return this._object[this._key]
    }

    // 传递的类型必须是O[K]的类型
    set value(newValue: O[K]) {
        this._object[this._key] = newValue
    }
}

class User {
    constructor(public name: string, public age: number) { }
}

let obj1 = new User('tao', 18)
let obj2 = new ObjectRef<User, 'name'>(obj1, 'name')
console.log(obj2.value);  //tao
obj2.value = 'shen'       //这里必须赋值string类型,因为new时 传递了'name',其属性是string
console.log(obj2.value);  //shen

泛型继承

interface Girl{
    name:string
}

T继承Girl
class SelectGril<T extends Girl> {
    constructor(ptivate girls: T[]){}
	getGril(index:number):string{
        return this.girls[index].name
    }
}

const girl = new SelectGril([
    {name:'tao'}
    {name:'shen'}
])

学习更多

TS学习地图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值