• TS: 泛型


    学 Java 的时候总会提到泛型,现在 TS 也有了,他们的用法都差不太多。泛型可以理解为广泛的类型。

    为什么要用泛型

    先来了解下泛型有什么用。先看下面定义的一个函数:

    function itself(a: number): number {
        return a
    }
    
    itself(1) // 1

    上面的函数就是简单的传入一个数,返回一个数,但是现在想传入字符串,返回字符串呢?或者再加传入数组,返回数组呢?这就需要用到泛型了。

    function itself<T>(a: T):T {
        return a
    }
    
    console.log(itself(true)) // true
    console.log(itself(1))   // 1
    console.log(itself('1')) // '1'
    console.log(itself([1, 2, 3])) // [1, 2, 3]

    从上面的例子可以看到,T 有点像是一个临时变量一样,先推断出传入参数的类型,将这个类型赋值到 T T = XXX 类型,后面就直接 返回的类型 = T = XXX 类型。这么说可能不那么准确,但是可以看到 T 就是一个占位符。

    如果调用函数时使用显式声明可能会更直观。

    function itself<T>(a: T):T {
        return a
    }
    
    console.log(itself<boolean>(true)) // true
    console.log(itself<number>(1))   // 1
    console.log(itself<string>('1')) // '1'
    console.log(itself<Array<number>>([1, 2, 3])) // [1, 2, 3

    这里发现 Array<number> 里也是用了泛型的,这样可以声明数组里元素的类型。

    接口与泛型

    上面都是传基本类型(除了 Array),下面看看接口与泛型的配合。

    interface Human {
        name: string
        age: number
    }
    interface Animal {
        category: string
    }
    
    function create<T>(what: T): T {
        return what
    }
    
    create<Human>({
        name: 'Jack',
        age: 18
    })
    
    create<Animal>({
        category: 'dog'
    })

    用法几乎一样,Easy~。

    有了接口这个东西后,我们可以玩更高级一点的。现在我想造一个 Human,规定这个 Human 一定要有 JJ,可以这么写。

    interface JJ {
        jjSize: string
        jjLength: number
    }
    interface Human {
        name: string
        age: number
    }
    
    function create<T extends JJ>(what: T): T {
        return what
    }
    
    create({
        name: 'Jack',
        age: 18,
        jjSize: 'large',
        jjLength: 18
    })
    
    create({
        name: 'Jack',
        age: 18
    }) // 报错:没有 jjSize 和 jjLength

    上面的这个用法叫做泛型的约束,像刚刚说的这个 Human 一定要有 JJ,这就是一个约束。

    类与泛型

    说完接口,肯定逃不了要说类了。我们先来看一段 JS 的代码。

    function create(C) {
        return new C()
    }

    正确的理解应该是传入一个构造函数 C,然后返回 C 的实例,没了。但是这个函数啥约束都没有,如果传入一个字符串 "Hello" 呢?那不是炸了?所以我们要用 TS 里的泛型去约束它。

    function create<T>(C: { new () }) {
        return new C()
    }

    两个括号里写的是 new () 说明传入的 C 是可以用 new C() 的。然后我们再加个上返回类型和传入的类型,可以写成这样。

    function create<T>(c: { new (): T }): T {
        return new c()
    }
  • 相关阅读:
    CSS3的常用属性(一)
    Shiro授权认证原理和流程
    mysql存储引擎
    mysql索引的注意事项
    CSS的常用属性(三)
    CSS的常用属性(二)
    CSS的常用属性(一)
    常用文档站点
    Spring和SpringMVC父子容器关系初窥
    内部类学习资料分享
  • 原文地址:https://www.cnblogs.com/plBlog/p/12375840.html
Copyright © 2020-2023  润新知