I remember C# being great a few years back when I used it. I am surprised that it doesn't have better discriminated unions since languages like TypeScript, and F# have them.
Is the interop between C# and F# not good? I've never used it myself, but I remember (and this is validated by a quick web search) that it's possible to just directly call F# code.
TypeScript only has "discriminated unions" in an extremely busted form. While they are encoded in its type system, there is little support in control flow. Exhaustiveness checking is essentially optional: it's enabled in switch statements by either `assertNever` in the `default` case, or by limiting your function return from within switch cases with the `strictNullChecks` option enabled.
Without a match expression and first-class exhaustiveness checking, discriminated unions are far less useful. Of course, this is because they don't want the TypeScript compiler to actually generate code, so they can't add runtime features. While TypeScript is better than no TypeScript, it seems like a massive waste to build a compiler and then shy away from making people's lives easier when possible.
> it's enabled in switch statements by either `assertNever` in the `default` case, or by limiting your function return from within switch cases with the `strictNullChecks` option enabled.
What's wrong with using if statements?
```
if(shape.key === 'rectangle'){}
else if (shape.key === 'circle') {}
else {x: never = shape} // todo: use exhaustiveCheck(x: never)
F# discriminated unions are always heap-allocated - the .Net runtime doesn't currently support address punning (having a single memory location possibly be a heap value or a stack value is UB). That may (always profile) put you at odds with writing fast code - and probably will: remember that significant portions of aspnetcore's recently skyrocketing performance have come down to eliminating allocations.
F# does have [<Struct>] DUs now but I believe because of the runtime limitations you mention, it ends up as sizeof(fields of case 1 + fields of case 2 + ...). They might reuse fields of the same type so if your DU cases can carry an A of string or B of string*int, the underlying struct is sizeof(string+int) not sizeof(string+string+int), but I'm not sure.
Regardless F#'s biggest downfall is that to use it you basically have to be a C# expert already and learn the F# syntax and additional features on top of that. Otherwise it's a baffling standalone language because you're left wondering why there are two ways to do almost everything -- Task vs Async, struct ("tup", "les") vs ("regular", "tuples"), two kinds of extension methods for classes, Nullable<T> vs Option<T>, it goes on and on.
Is the interop between C# and F# not good? I've never used it myself, but I remember (and this is validated by a quick web search) that it's possible to just directly call F# code.