Typescript 差异联合类型和区分联合类型脚本/F#
所以我读了Typescript关于工会类型的官方文档,我认为这和F#中的“歧视工会”是一样的(尽管它们有不同的语法,但概念相同),因为我有F#背景,而且两者都有微软的支持。但看看这些文件,F#并没有真正区分“工会类型”和“歧视工会”: 但是,Typescript确实区分了这两个概念: 联合类型: 受歧视的工会: 所以我想知道这些概念本身是否真的有区别,或者仅仅是一些依赖于语言的概念 到目前为止,我所了解的是F#中的并集类型也是有区别的并集,因为可以使用匹配表达式和解构来区分并集类型Typescript 差异联合类型和区分联合类型脚本/F#,typescript,functional-programming,f#,union-types,Typescript,Functional Programming,F#,Union Types,所以我读了Typescript关于工会类型的官方文档,我认为这和F#中的“歧视工会”是一样的(尽管它们有不同的语法,但概念相同),因为我有F#背景,而且两者都有微软的支持。但看看这些文件,F#并没有真正区分“工会类型”和“歧视工会”: 但是,Typescript确实区分了这两个概念: 联合类型: 受歧视的工会: 所以我想知道这些概念本身是否真的有区别,或者仅仅是一些依赖于语言的概念 到目前为止,我所了解的是F#中的并集类型也是有区别的并集,因为可以使用匹配表达式和解构来区分并集类型 但是,您不能
但是,您不能使用Typescript进行区分,因为该语言没有提供具体的表达式来进行区分,因此您需要通过所有联合类型都具有的值来进行区分,即区分器。这是否正确?类型并集
(a | B)
中的操作数都是类型,而区分并集类型U=a | B
中的情况都是类型U
的构造函数,本身不是类型。类型U
的值在运行时被标记,以便您可以区分可能的情况
一个结果是,可以以联合类型可能不会的方式嵌套有区别的联合。联合类型系统中某些类型A
的可选值可以表示为
type A? = (A | null)
type a' option = Some of 'a | None
其中null
是null
值的单例类型
对于一个受歧视的联盟,它通常被表示为
type A? = (A | null)
type a' option = Some of 'a | None
用这个公式计算出的值
let o: int option option = Some None
不能用联合类型表示,因为
(A?)
=(A | null)| null
=A | null
=A?
主要区别在于,Typescript联合类型实际上是F#判别联合的超集
类型脚本联合类型=未标记的联合类型。F#区分的联合=标记的联合类型 换句话说,每一个可以用F#建模的有区别的并集都可以用Typescript并集类型进行同构建模,但反之则不然 例如,F#中的以下歧视并集: 可以在Typescript中进行同构建模,如下所示:
type Option<T> = {tag: 'Some', value: T} | {tag: 'None'}
这里的主要区别是TypeScript联合类型不需要标记,但是F#联合类型必须标记
因此,我们可以看到TypeScript实际上比F#更灵活,但是这并不是没有成本的,未标记的联合实际上是多孔的,这意味着有一些类型联合,TypeScript将无法进行类型检查
这就像非类型lambda演算是类型lambda演算的超集,但类型lambda演算更容易证明正确。是的,TS中的判别式只是您选择的一个偶然对象属性。对于区分的或标记的联合,您不需要这样做,因为类型本身携带这些信息。由于标记在编译过程中不会被删除,所以您可以在运行时对其进行模式匹配。当然,您可以。我非常喜欢您基于类型构造函数思想的解释,这更有意义。但是,为什么嵌套的联合不能与联合类型一起工作呢?如您所示,是谁“简化”了类型?为什么有区别的联合可以与嵌套类型一起工作呢?所以联合类型基本上允许对可能的多个类型使用类型别名,而有区别的联合不能这样做,它们只能对一种类型使用类型别名。正如@Lee在他的回答中提到的,对于有区别的联合,我们需要类型构造函数,即“cases”或标记标签。定义区分的联合就是为一个类型指定不同的类型构造函数。对于联合类型,我们可以定义其他类型的类型别名。