Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference union types and discriminated unions typescript/F#

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?

like image 910
FraK Avatar asked Dec 18 '22 13:12

FraK


1 Answers

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.

like image 134
Wong Jia Hau Avatar answered Jan 14 '23 03:01

Wong Jia Hau