So I was reading the official docs of Typescript about union types, and I was thinking that it is the same as "discriminated unions" in F# (granted they have different syntax but same concept), as I have a F# background and given the fact that both are backed by Microsoft. But looking at the docs, F# doesn't really make a distinction between "union types" and "discriminated unions": https://fsharpforfunandprofit.com/posts/discriminated-unions/
However, Typescript does make a distinction between these two concepts:
Union types: https://www.typescriptlang.org/docs/handbook/advanced-types.html#union-types
Discriminated Unions: https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions
So I was wondering if there is really a distinction in the concepts themselves or is just some language dependent concept?
What I understand so far is that union types in F# are also discriminated unions because you can discriminate the union type using match expressions and deconstructing.
However, you cannot do the discrimination with Typescript as the language does not provide a specific expression to do that, so yo need to discriminate by a value, that all union types have, the discriminant. Is this correct?
The main difference is that, Typescript Union Type is actually a superset of F# Discriminated Union.
TypeScript Union Type = Untagged union type.
F# Discriminated Union = Tagged union type.
In other words, every discriminated union that can be modelled in F# can be modelled isomorphically in Typescript union type, however the reverse is not true.
For example, the following discriminated union in F#:
type a' Option = Some of 'a | None
Can be modelled isomorphically in Typescript as:
type Option<T> = {tag: 'Some', value: T} | {tag: 'None'}
However, the following Typescript union type cannot be modelled isomorphically in F#:
type UserInput = number | string
The main difference here is TypeScript union type do not need be tagged, however F# union type must be tagged.
Thus, we can see that TypeScript is actually more flexible than F#, however this does not come without cost, untagged union are actually holey, meaning there are some type union where TypeScript will fail to type-check.
It's like untype lambda calculus is superset of typed lambda calculus, but type lambda calculus is much more easier to proof right.