So a Sum Type is a type that can be one of many variants. In Rust this could be something like
enum CustomType {
String(String),
Number(f64),
}
(note: naming of String and Number is arbitrary here)
Where a variable of type CustomType can be either CustomType::String (in which case it contains a string) or CustomType::Number (in which case it contains a number (specifically a 64bit float)).
In typescript this same type would be:
type CustomType = string | number;
A feature of sum types (in contrast to C/C++ "unions" which are an otherwise similar concept) is that they store which variant a current variable is using. So in Rust you can do:
let foo_or_bar = CustomType::Bar(1);
match foo_or_bar {
CustomType::String(string) => { /* foo_or_bar is String */ },
CustomType::Number(number) => { /* foo_or_bar is Number */ },
}
And in TypeScript (and JavaScript!) you can do:
let fooOrBar = 1;
switch(typeof fooOrBar) {
case "number":
// fooOrBar is a number
break;
case "string":
// fooOrBar is a string
break;
Now notice that a JavaScript variable (or a variable of type `any` in typescript) is essentially the same as this except there are more options. If you were to model it in Rust you might have something like:
enum JSValue {
Null,
Undefined,
Boolean(bool),
Number(f64),
String(String),
Array(Vec<JSValue>),
Object(HashMap<String, JSValue>),
Function(fn),
}
With perhaps some more types to handle variants to handle less common types like big numbers, typed arrays, etc. And in JavaScript this is just the default type that applies to all variables! And as it applies to all variables you don't have to specify that a variable is of type JSValue, you just specify the inner type to be 7 or false or null or "foo" or whatever and it chooses the correct variant for you. But internally the JS engine is keeping track of what type your variable is, and it allows you to query it at runtime (although it may not be as simple as typeof).