摘要:往期第一课体验第二课基础类型和入门高级类型第三课泛型第四课解读高级类型插一课本来打算接着上节课把高级类型都讲完但是写着写着我发现高级类型中有很多地方都需要泛型的知识那么先插一节泛型什么是类型变量和泛型变量的概念我们都知道可以表示任意数据类型
往期
第一课, 体验typescript
第二课, 基础类型和入门高级类型
第三课, 泛型
第四课, 解读高级类型
插一课本来打算接着上节课, 把高级类型都讲完, 但是写着写着我发现高级类型中, 有很多地方都需要泛型的知识, 那么先插一节泛型.
什么是"类型变量"和"泛型"变量的概念我们都知道, 可以表示任意数据, 类型变量也一样, 可以表示任意类型:
// 在函数名后面用"<>"声明一个类型变量 function convert(input:T):T{ return input; }
convert中参数我们标记为类型T, 返回值也标记为T, 从而表示了: 函数的输入和输出的类型一致. 这样使用了"类型变量"的函数叫做泛型函数, 那有"泛型类"吗?
注意: T是我随便定义的, 就和变量一样, 名字你可以随便起, 只是建议都是大写字母,比如U / RESULT.
class Person { who: U; constructor(who: U) { this.who = who; } say(code:U): string { return this.who + " :i am " + code; } }
在类名后面通过"<>"声明一个类型变量U, 类的方法和属性都可以用这个U, 接下来我们使用下泛型类:
let a = new Person("詹姆斯邦德"); a.say(007) // 错误, 会提示参数应该是个string a.say("007") // 正确
我们传入了类型变量(string),告诉ts这个类的U是string类型, 通过Person的定义, 我们知道say方法的参数也是string类型, 所以a.say(007)会报错, 因为007是number. 多以我们可以通过传入类型变量来约束泛型.
其实我们也可以不指定类型变量为string, 因为ts可以根据实例化时传入的参数的类型推断出U为string类型:
let a = new Person("詹姆斯邦德"); // 等价 let a = new Person("詹姆斯邦德"); a.say(007) // 错误, 会提示参数应该是个string a.say("007") // 正确
其实方法和函数的定义方式一样:
class ABC{ // 输入T[], 返回T getFirst(data:T[]):T{ return data[0]; } }
说实话ts的文档我找了好几遍, 也没看到他给泛型正式做定义, 只是表达他是一种描述多种类型(类型范围)的格式, 我觉得有点抽象, 我用自己的理解具象下: 用动态的类型(类型变量)描述函数和类的方式.
泛型类型我们可以用类型变量去描述一个类型(类型范围), ts的数组类型Array本身就是一个泛型类型, 他需要传递具体的类型才能变的精准:
let arr : Array; arr = ["123"]; // 错误, 提示数组中只可以有number类型 arr = [123];
下面我们自己定义一个泛型类型, 就对开头的convert函数定义:
function convert泛型接口(input:T):T{ return input; } // 定义泛型类型 interface Convert { (input:T):T } // 验证下 let convert2:Convert = convert // 正确不报错
通过传入不同的类型参数, 让属性更灵活:
interface Goods扩展类型变量(泛型约束){ id:number; title: string; size: T; } let apple:Goods = {id:1,title: "苹果", size: "large"}; let shoes:Goods = {id:1,title: "苹果", size: 43};
function echo(input: T): T { console.log(input.name); // 报错, T上不确定是否由name属性 return input; }
前面说过T可以代表任意类型, 但对应的都是基础类型, 所以当我们操作input.name的时候就需要标记input上有name属性, 这样就相当于我们缩小了类型变量的范围, 对泛型进行了约束:
// 现在T是个有name属性的类型 function echo一个泛型的应用, 工厂函数(input: T extends {name:string}): T { console.log(input.name); // 正确 return input; }
function create(O: {new(): T|U; }): T|U { return new O(); }
主要想说3个知识点:
可以定义多个类型变量.
类型变量和普通类型用法一直, 也支持联合类型/交叉类型等类型.
如果一个数据是可以实例化的, 我们可以用{new(): any}表示.
不要乱用泛型泛型主要是为了约束, 或者说缩小类型范围, 如果不能约束功能, 就代表不需要用泛型:
function convert(input:T[]):number{ return input.length; }
这样用泛型就没有什么意义了, 和any类型没有什么区别.
总结泛型是编译型语言最重要的特性, 泛型写的好就会让人觉得代码很高级, 可以说泛型是一个成手ts程序员必须熟练的技巧, 面试的时候是加分项, 所以大家写代码多多用泛型练习哦, 加油ヾ(◍°∇°◍)ノ゙,下面是的用ts写的几个小项目,写的不好, 就是有份热情, 抛砖引玉, 大家肯定能写出更好的:
手势库: https://github.com/any86/any-...
命令式调用vue组件: https://github.com/any86/vue-...
工作中常用的一些代码片段: https://github.com/any86/usef...
一个mini的事件管理器: https://github.com/any86/any-...
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/105671.html
摘要:更新啦第一课体验第二课基础类型和入门高级类型第三课泛型第四课解读高级类型要来了看了的视频特别兴奋要来了是用开发的我揣测在的带领下会成为主流呢要不先学点年最酷的前端技术我是年初开始使用的自从开始用上了就喜欢上了真的爱不释手最爱他几点很多小错误 更新啦 第一课, 体验typescript 第二课, 基础类型和入门高级类型 第三课, 泛型 第四课, 解读高级类型 vue3要来了 看了vue ...
摘要:导航第一课体验第二课基础类型和入门高级类型第三课泛型第四课解读高级类型很重要这一节很重要可以说是的最核心部分这一节学完其实就可以开始用写代码了想想中的再看看标题中的类型字所以请大家务必认真什么是入门高级类型因为高级类型的内容比较多但是有些基 导航 第一课, 体验typescript 第二课, 基础类型和入门高级类型 第三课, 泛型 第四课, 解读高级类型 很重要 这一节很重要, 可以说...
摘要:往期目录第一课体验第二课基础类型和入门高级类型第三课什么是泛型第四课解读高级类型第五课什么是命名空间什么时候要用命名空间如果你发现自己写的功能函数类接口等越来越多你想对他们进行分组管理就可以用命名空间下面先用类举例仔细看你会发现下还有在这里 往期目录 第一课, 体验typescript 第二课, 基础类型和入门高级类型 第三课, 什么是泛型? 第四课, 解读高级类型 第五课, 什么是命...
摘要:直达第一课体验第二课基础类型和入门高级类型第三课泛型第四课解读高级类型第五课什么是命名空间回顾第二课的时候为了更好的讲解基础类型所以我们讲解了一部分高级类型比如接口联合类型交叉类型本节课我会把剩余高级类型都讲完知识点摘要本节课主要关键词为自 直达 第一课, 体验typescript 第二课, 基础类型和入门高级类型 第三课, 泛型 第四课, 解读高级类型 第五课, 什么是命名空间(na...
阅读 804·2023-04-25 19:40
阅读 3405·2023-04-25 17:41
阅读 2993·2021-11-11 11:01
阅读 2587·2019-08-30 15:55
阅读 3217·2019-08-30 15:44
阅读 1347·2019-08-29 14:07
阅读 478·2019-08-29 11:23
阅读 1314·2019-08-27 10:54