- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章来做操吧!深入 TypeScript 高级类型和类型体操由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
TypeScript 给 JavaScript 扩展了类型的语法,我们可以给变量加上类型,在编译期间会做类型检查,配合编辑器还能做更准确的智能提示。此外,TypeScript 还支持了高级类型用于增加类型系统的灵活性.
就像 JavaScript 的高阶函数是生成函数的函数,React 的高阶组件是生成组件的组件一样,Typescript 的高级类型就是生成类型的类型.
TypeScript 高级类型是通过 type 定义的有类型参数(也叫泛型)的类型,它会对传入的类型参数做一系列的类型计算,产生新的类型.
比如,这个 Pick 就是一个高级类型,它有类型参数 T 和 K,类型参数经过一系列的类型计算逻辑,会返回新的类型.
TypeScript 高级类型会根据类型参数求出新的类型,这个过程会涉及一系列的类型计算逻辑,这些类型计算逻辑就叫做类型体操。当然,这并不是一个正式的概念,只是社区的戏称,因为有的类型计算逻辑是比较复杂的.
TypeScript 的类型系统是图灵完备的,也就是说它能描述任何可计算逻辑,简单点来说就是循环、条件判断等该有的语法都有.
既然 TypeScript 的类型系统这么强,那我们就做一些高级类型的类型体操来感受下吧.
我们会做这些体操:
我把这些体操分为数字类的、字符串类的、对象类的,把这三种类型计算逻辑的规律掌握了,相信你的体操水平会提升一截.
在做体操之前,要先过一下 TypeScript 的类型语法,也就是能做哪些类型计算逻辑.
既然说该有的语法都有,那我们来看下循环和判断都怎么做:
ts 类型的条件判断的语法是 条件 ? 分支1 : 分支2 .
extends 关键字是用于判断 A 是否是 B 类型的。例子中传入的类型参数 T 是 1,是 number 类型,所以最终返回的是 true.
ts 类型没有循环,但可以用递归来实现循环.
我们要构造一个长度为 n 的数组,那么就要传入长度的类型参数 Len、元素的类型参数 Ele、以及构造出的数组的类型参数 Arr(用于递归).
然后类型计算逻辑就是判断 Arr 的 length 是否是 Len,如果是的话,就返回构造出的 Arr,不是的话就往其中添加一个元素继续构造.
这样,我们就递归的创建了一个长度为 Len 的数组.
ts 支持构造新的字符串:
也支持根据模式匹配来取字符串中的某一部分:
因为 str 符合 aaa, 的模式,所以能够匹配上,把右边的部分放入通过 infer 声明的局部类型变量里,之后取该局部变量的值返回.
ts 类型的对象操作ts 支持对对象取属性、取值:
也可以创建新的对象类型:
通过 keyof 取出 obj 的所有属性名,通过 in 遍历属性名并取对应的属性值,通过这些来生成新的对象类型 newObj.
我们过了一下常用的 ts 类型的语法,包括条件判断、循环(用递归实现)、字符串操作(构造字符串、取某部分子串)、对象操作(构造对象、取属性值)。接下来就用这些来做操吧.
我们把体操分为 3 类来练习,之后再分别总结规律.
体操 1:实现高级类型 Add,能够做数字加法.
ts 类型能做数字加法么?肯定可以的,因为它是图灵完备的,也就是各种可计算逻辑都可以做.
那怎么做呢?
数组类型可以取 length 属性,那不就是个数字么。可以通过构造一定长度的数组来实现加法.
上文我们实现了通过递归的方式实现了构造一定长度的新数组的高级类型:
那只要分别构造两个不同长度的数组,然后合并到一起,再取 length 就行了.
我们测试下:
我们通过构造数组的方式实现了加法.
小结下:ts 的高级类型想做数字的运算只能用构造不同长度的数组再取 length 的方式,因为没有类型的加减乘除运算符.
体操2:把字符串重复 n 次.
字符串的构造我们前面学过了,就是通过 ${A}${B} 的方式,那只要坐下计数,判断下重复次数就行了.
计数涉及到了数字运算,要通过构造数组再取 length 的方式.
所以,我们要递归的构造数组来计数,并且递归的构造字符串,然后判断数组长度达到目标就返回构造的字符串.
所以有 Str(待重复的字符串)、Count(重复次数)、Arr(用于计数的数组)、ResStr(构造出的字符串)四个类型参数:
我们递归的构造了数组和字符串,判断构造的数组的 length 如果到了 Count,就返回构造的字符串 ResStr,否则继续递归构造.
测试一下:
小结:递归构造字符串的时候要通过递归构造数组来做计数,直到计数满足条件,就生成了目标的字符串.
这个体操只用到了构造字符串,没用到字符串通过模式匹配取子串,我们再做一个体操.
体操3: 实现简易的 JS Parser,能解析字符串 add(11,22) 的函数名和参数 。
字符串的解析需要根据模式匹配取子串。这里要分别解析函数名(functionName)、括号(brackets)、数字(num)、逗号(comma),我们分别实现相应的高级类型.
函数名是由字母构成,我们只要一个个字符一个字符的取,判断是否为字母,是的话就记录下该字符,然后对剩下的字符串递归进行同样的处理,直到不为字母的字符,通过这样的方式就能取出函数名.
我们先定义字母的类型:
还有保存中间结果的类型:
然后就一个个取字符来判断,把取到的字符构造成字符串存入中间结果:
我们取了单个字符,然后判断是否是字母,是的话就把取到的字符构造成新的字符串,然后继续递归取剩余的字符串.
测试一下:
符合我们的需求,我们通过模式匹配取子串的方式解析出了函数名.
然后继续解析剩下的.
括号的匹配也是同样的方式,而且括号只有一个字符,不需要递归的取,取一次就行.
测试一下:
继续解析剩下的:
解析数字 。
数字的解析也是一个字符一个字符的取,判断是否匹配,匹配的话就递归取下一个字符,直到不匹配:
测试一下:
继续解析剩下的:
逗号和括号一样,只需要取一个字符判断即可,不需要递归.
测试一下:
至此,我们完成了所有的字符的解析,解析来按照顺序组织起来就行.
单个 token 的解析都做完了,整体解析就是组织下顺序,每次解析完拿到剩余的字符串传入下一个解析逻辑,全部解析完,就可以拿到各种信息.
测试一下:
大功告成,我们用 ts 类型实现了简易的 parser.
小结:ts 类型可以通过模式匹配的方式取出子串,我们通过一个字符一个字符的取然后判断的方式,递归的拆分出 token,然后按照顺序拆分出 token,就能实现字符串的解析.
完整代码如下:
体操4:实现高级类型,取出对象类型中的数字属性值 。
构造对象、取属性名、取属性值的语法上文学过了,这里组合下就行:
我们构造一个新的对象类型,通过 keyof 遍历对象的属性名,然后对属性值做判断,如果不是数字就返回 never,然后再取属性值.
属性值返回 never 就代表这个属性不存在,就能达到过滤的效果.
测试一下:
小结:对象类型可以通过 {} 构造新对象,通过 [] 取属性值,通过 keyof 遍历属性名,综合这些语法就可以实现各种对象类型的逻辑.
TypeScript 给 JavaScript 扩展了类型的语法,而且还支持了高级类型来生成类型.
高级类型是通过 type 声明的带有类型参数的类型,类型参数也叫泛型。根据类型参数生成最终类型的类型计算逻辑被戏称为类型体操.
TypeScript 的类型系统是图灵完备的,可以描述任何可计算逻辑:
我们分别做了这些类型体操:
其中要注意的就是数字类的要通过构造数组取长度的方式来计算,再就是字符串的模式匹配取子串,这两个是相对难度大一些的.
其实各种高级类型,只要熟悉了 ts 类型语法,想清楚了逻辑就能一步步写出来,和写 JS 逻辑没啥本质区别,只不过它是用于生成类型的逻辑.
读到这里,是不是感觉高级类型的类型体操也没有啥难度了呢?
原文链接:https://mp.weixin.qq.com/s/z5N3ePnhAo4liYaZLfwtog 。
最后此篇关于来做操吧!深入 TypeScript 高级类型和类型体操的文章就讲到这里了,如果你想了解更多关于来做操吧!深入 TypeScript 高级类型和类型体操的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在尝试编写一个相当多态的库。我遇到了一种更容易表现出来却很难说出来的情况。它看起来有点像这样: {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE
谁能解释一下这个表达式是如何工作的? type = type || 'any'; 这是否意味着如果类型未定义则使用“任意”? 最佳答案 如果 type 为“falsy”(即 false,或 undef
我有一个界面,在IAnimal.fs中, namespace Kingdom type IAnimal = abstract member Eat : Food -> unit 以及另一个成功
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: What is the difference between (type)value and type(va
在 C# 中,default(Nullable) 之间有区别吗? (或 default(long?) )和 default(long) ? Long只是一个例子,它可以是任何其他struct类型。 最
假设我有一个案例类: case class Foo(num: Int, str: String, bool: Boolean) 现在我还有一个简单的包装器: sealed trait Wrapper[
这个问题在这里已经有了答案: Create C# delegate type with ref parameter at runtime (1 个回答) 关闭 2 年前。 为了即时创建委托(dele
我正在尝试获取图像的 dct。一开始我遇到了错误 The function/feature is not implemented (Odd-size DCT's are not implemented
我正在尝试使用 AFNetworking 的 AFPropertyListRequestOperation,但是当我尝试下载它时,出现错误 预期的内容类型{( “应用程序/x-plist” )}, 得
我在下面收到错误。我知道这段代码的意思,但我不知道界面应该是什么样子: Element implicitly has an 'any' type because index expression is
我尝试将 SignalType 从 ReactiveCocoa 扩展为自定义 ErrorType,代码如下所示 enum MyError: ErrorType { // .. cases }
我无法在任何其他问题中找到答案。假设我有一个抽象父类(super class) Abstract0,它有两个子类 Concrete1 和 Concrete1。我希望能够在 Abstract0 中定义类
我想知道为什么这个索引没有用在 RANGE 类型中,而是用在 INDEX 中: 索引: CREATE INDEX myindex ON orders(order_date); 查询: EXPLAIN
我正在使用 RxJava,现在我尝试通过提供 lambda 来订阅可观察对象: observableProvider.stringForKey(CURRENT_DELETED_ID) .sub
我已经尝试了几乎所有解决问题的方法,其中包括。为 提供类型使用app.use(express.static('public'))还有更多,但我似乎无法为此找到解决方案。 index.js : imp
以下哪个 CSS 选择器更快? input[type="submit"] { /* styles */ } 或 [type="submit"] { /* styles */ } 只是好
我不知道这个设置有什么问题,我在 IDEA 中获得了所有注释(@Controller、@Repository、@Service),它在行号左侧显示 bean,然后转到该 bean。 这是错误: 14-
我听从了建议 registering java function as a callback in C function并且可以使用“简单”类型(例如整数和字符串)进行回调,例如: jstring j
有一些 java 类,加载到 Oracle 数据库(版本 11g)和 pl/sql 函数包装器: create or replace function getDataFromJava( in_uLis
我已经从 David Walsh 的 css 动画回调中获取代码并将其修改为 TypeScript。但是,我收到一个错误,我不知道为什么: interface IBrowserPrefix { [
我是一名优秀的程序员,十分优秀!