3 ms·
Type-safe tagged unions, one of the nicest features of Typescript: interface Foo { type: "foo"; name: string; } interface Bar { type: "bar"; size: numb
by incrudible 5y ago
Type-safe tagged unions, one of the nicest features of Typescript:
interface Foo { type: "foo"; name: string; }
interface Bar { type: "bar"; size: number; }
type Variant = Foo | Bar;
function tell(x: Variant) {
switch (x.type) {
case "foo":
// x now has type Foo
console.log(`The name is {x.name}`);
break;
case "bar":
// x now has type Bar
console.log(`The size is {x.size.toFixed(2)}`);
break;
default:
// statically unreachable
}
}
Hope to see this in Python type checkers as well.
- NoThisIsMe 5y agoTypescript is so weird. Like this is cool I guess but I'd much rather just match on `Foo` or `Bar` directly. But Typescript doesn't have pattern matching so it compensates with this bizarre paradigm of enforcing dynamic type checks statically.
- jakear 5y agoYou can check instanceof of course, but the idea behind doing this is that object literals and raw data from JSON/whatever can be treated as a first class entity, rather than mucking around with all the boilerplate dataclass junk a lot of languages get tangled up in.
- azkae 5y agoYou can already do this without pattern matching: from typing import Union, NoReturn class Foo: name: str class Bar: size: int Variant = Union[Foo, Bar] # or `Foo | Bar` in Python 3.10 def assert_never(x: NoReturn) -> NoReturn: # runtime error, should not happen raise Exception(f'Unhandled value: {x}') def tell(x: Variant): if isinstance(x, Foo): print(f'name is {x.name}') elif isinstance(x, Bar): print(f'name is {x.size}') else: assert_never(x) mypy returns an error if you don't handle all cases.
- incrudible 5y agoThe difference is that in Typescript, this works on any structurally matching object that you may get e.g. through JSON.