这被称为相关记录类型,在 TypeScript 社区中有相当多的讨论。我的方法是将相关记录检查移至运行时:
https://github.com/microsoft/TypeScript/issues/30581#issuecomment-686621101
https://repl.it/@urgent/runtime-fp-ot
步骤1
创建一个包含Prop
所有允许属性的通用接口。
interface Prop {
label: "user" | "post",
userid: string,
body: string
}
这确实会阻止类型特定的属性,并且您可能会发生冲突。user.id
想成为一个number
但post.id
想成为一个string
。对我来说没什么大不了的。考虑一个特定于您的类型的不同属性名称,接受那里的内容,或者如果您喜欢冒险尝试添加维度Props
并按类型索引。
第2步
创建标签映射到运行时解码器。在打字稿中,我使用了一个类,因此我可以通过不同的文件对其进行扩展:
class Decoder {
user: userDecode,
post: postDecode
}
第 3 步
创建一个函数,该函数接受 props,从类原型中查找解码器,并执行运行时解码
(props:Props) => Decoder.prototype[props.label].decode(props as any)
io-ts 需要any
在严格模式下扩大。您还需要一个props.label
存在于Decoder
第4步
创建类似的功能图来运行。如果您在运行时解码后调用它们,您就知道运行时正在传递有效值。
缺点
- 比写出和管理 switch 语句要复杂得多。TypeScript 类型
switch
自动缩小。
- 财产冲突。没有添加工作的类型没有特定属性。
- 需要手动检查类型是否存在。
switch
将忽略,并使用默认情况
优点
- 您可以永久关闭运行时处理。隔离,如果您需要添加对不同运行时类型的支持,则无需打开该代码。
- 在为不同的运行时类型创建支持时,例如
page
or file
,类似 babel 文件的东西可以自动导入新文件。
- 适合版本控制和开发人员访问权限。可以开放新类型供公众提交。核心处理可以保持关闭。所以你有一个 DSL 的开始。