【随笔领悟】程序语言的“关键字”与数学符号

28 阅读2分钟

今天早上在做类型体操的“first”这一题。 我学习到了 “infer” 关键词的用法。

type-challenges/README.zh-CN.md at main · type-challenges/type-challenges · GitHub (kgithub.com)

对我来说,这是在接触一个新概念,我不禁开始思考一些逻辑学的事情:

  1. 我如何基于已有的逻辑,推理出新的逻辑?
  2. 程序语言中的“关键词”到底应该怎么去理解/使用/记忆?
type arr1 = ["a", "b", "c"];
type arr2 = [3, 2, 1];

type head1 = First<arr1>; // expected to be 'a'
type head2 = First<arr2>; // expected to be 3

type First<Arr> = Arr extends { 0: infer Index0Type } ? Index0Type : never;

适宜人脑直接思考的逻辑思维:语义化表述。

“想出新逻辑”的过程就是:将多个 “语义片段” 随意组合起来。或者对已有逻辑中的语义片段做 “同类替换”。

关注程序语言中 extends,infer,?,特殊结构(比如{0: infer xxx}) 所代表的“语义”

所谓的“语义”就是一大串自然语言的解释。

就像逻辑学 / 数学 习惯于将一大串“语义”然后赋予到一个简洁的特殊符号 “->” 上一样。

我只需要真正学会赋予给 “extends,infer,?” 这些符号的语义,我就能完成编程。

一般来说,提出这些符号的 “RFC提案” 中就蕴含了这些符号的设计者们,赋予给这个符号的语义。

然后下一步

将复杂语义寄宿在简单符号中,我们仅仅使用简洁语句,就能进行包含丰富语义的思考

降低了复杂逻辑所需要的思维量,变相提升逻辑思维能力。

我尝试用这种思维方式,做下一题

type-challenges/README.zh-CN.md at main · type-challenges/type-challenges · GitHub (kgithub.com)

type ExampleType = Promise<string>;

type Result = MyAwaited<ExampleType>; // string

type MyAwaited<T> = T extends Promise<infer P> ? P : never;

基于我今天提出的 “理解关键字/符号背后寄宿的 ‘语义片段’” 这一方法

我在做这题的时候

简单地把题目给出的语义先理解了一次。

然后把我脑子里存储的 extends的语义,infer的语义,type XXX = {} 这个语法结构的语义,都遍历了一次。

我先做好接口设计。MyAwaited (“接口”就是别人如何调用你的逻辑段落,参考OOAD思想)

做接口设计的时候我就想到,“T” 这个泛型,必须用extends做个约束,约束他必须是 Promise 的子类型

于是我就写出了如下代码

T extends Promise<P>

到这里思维就卡住了,于是我再次遍历所有 “关键词的语义”, 遍历到infer时我发现,“infer”的语义刚好是 “使用extends关键字时,extends右侧待推理的类型”

我再看向上面我写的代码 “Promise

” 刚好就在extends右侧!而且Promise

的 P 刚好就是我想要推理出的类型。

于是赶紧加上infer关键字

T extends Promise<infer P>

这题就解出来了。