slate 将 typescript 的型别扩充相关的内容都集合在 interfaces/custom-types.ts 这个 file 里面。
这个 file 的 code 是由一名叫 thesunny 的 contributor 针对新版 slate 处理 custom types 的修改建议。
因为在之前的版本,开发者需要在每次使用 api call 时都得重复以 generic 的形式传 custom-types ,这份 file 出现的目的正是让开发者在开发 slate project 时只需定义一次 custom-types 就能一劳永逸。
这里头主要功能的部分只有短短地不到 10 行,却利用了 interface
的 declaration merging 、 type
的 discriminating union 以及 unknown
的特性一次包办了整个 type customizing 所需的一切功能,笔者当初看到的时候觉得真的是太厉害了!特地拉成一整篇文章与各位读者分享。
我们先直接来看一下 custom-types.ts file 里面的 code
/**
* Extendable Custom Types Interface
*/
type ExtendableTypes =
| 'Editor'
| 'Element'
| 'Text'
| 'Selection'
| 'Range'
| 'Point'
| 'InsertNodeOperation'
| 'InsertTextOperation'
| 'MergeNodeOperation'
| 'MoveNodeOperation'
| 'RemoveNodeOperation'
| 'RemoveTextOperation'
| 'SetNodeOperation'
| 'SetSelectionOperation'
| 'SplitNodeOperation'
export interface CustomTypes {
[key: string]: unknown
}
export type ExtendedType<
K extends ExtendableTypes,
B
> = unknown extends CustomTypes[K] ? B : CustomTypes[K]
ExtendableTypes
不难理解,它就是事先为可以进行扩充的 types 做好限制,在 ExtendedType
吃的第一个 generic type 有限制了它的范围必须缩限在 ExtendableTypes 之中,这也是为什麽我们在 Day11 的 Example type 范例放进 ExtendedType
里是不会过关的原因。
CustomTypes
是主要让开发者定义 custom types 的 interface
,利用 interface
可以 extend 的特性让开发者可以透过 declare module 等方式扩充。
拿 slate 提供的 example code 作为范例,引入下方的 file 後 CustomTypes
就会多了 Editor
、 Element
、 Text
这三组 keys 的定义:
declare module 'slate' {
interface CustomTypes {
Editor: CustomEditor
Element: CustomElement
Text: CustomText | EmptyText
}
}
最後是最精华的 ExtendedType
utility ,它吃了两个 type generics 分别是:
ExtendableTypes
,负责比对 CustomTypes
中指定的 key 类型是否被扩充定义。CustomTypes
中被扩充定义的话会原封不动地回传 B 。让我们搭配最基本的 Text
type 协助我们介绍
/** text.ts */
export interface BaseText {
text: string
}
export type Text = ExtendedType<'Text', BaseText>
/** custom-types.ts */
export type ExtendedType<
K extends ExtendableTypes,
B
> = unknown extends CustomTypes[K] ? B : CustomTypes[K]
'Text'
与 BaseText
传入 ExtendedType
以後,它首先会确认 'Text'
是否存在於 ExtendableTypes
里。unknown extends CustomTypes[K]
的三元判断式,这里运用了 unknown
只会 extends unknown
这项特性,当判断结果为 true 时代表开发者未在 CustomTypes
里对 K 做扩充,回传 base-type 给 Text
,反之则回传 CustomTypes
里 K
对应到的扩充内容给 Text
。最後再附上 Slate Github issue 的讨论串,笔者在深入了解以前都只是照着 slate 提供的 example code 依样画葫芦而已,一直将纳闷放在心中。希望今天的分享也能让读者们体会笔者当时备受震慑的心情 XD
到这篇为止我们的 interface/ 章节终於要画上句点了,接下来我们要先花些篇幅来聊聊 Immutable 这项议题,以及它、 Immer.js 、 Slate 之间的关系。
咱们明天见罗~
<<: [Day 16] 阿嬷都看得懂的通用 .html 档案结构
>>: # Day16--ARC到底是虾饺?神秘的实体化背後的秘密
网页座标及应用 首先怎麽读取与显示座标。 座标的判断依据。 如何动态撷取浏览器宽高。 mousemo...
前言 因为公司前端资料已经处理成单层结构,所以都没注意到浅拷贝、深拷贝的实际差别。 在读完高手文章後...
为了维护专案程序码的品质,我们需要对提交的代码做各式的检查(例如: Lint 、 Format 、 ...
首先,我要先感谢老婆与家人的支持,让我有机会在 2021 年 ITHome 铁人赛完赛。其次感谢热心...
文书工作只能用 windows 吗? 在求学过程中,作业常常要求使用微软的 office 全家桶来进...