学 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() }
今天的文章TS: 泛型分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/51801.html