19 March 2023
A type alias defines a new name for a type using the type
keyword. For example, let’s
say we have a type for a 3-element vector. If we use those 3 elements for red, green, and blue, we
can use the same data structure for colors:
struct Vec3(f64, f64, f64);
type Color = Vec3;
Now we can use Color
and Vec3
pretty much interchangeably: we can assign
a Color
to a variable of type Vec3
and vice versa, define a method on one
type and call it on the other, define a function that takes one type and call it with the other, and
so on. The one thing we can’t do is use Color
as a constructor. For that we still need
Vec3
:
let c: Color = Vec3(0.5, 0.5, 1.0);
Type aliases are mostly used to avoid repetition with complex types. For example, some packages define their own Error type, and then also define a Result type like this:
type Result<T> = std::result::Result<T, Error>;
The use
keyword offers another way to define an alias:
struct Vec3(f64, f64, f64);
use Color = Vec3;
Here we can really use Color
in any place where we’d have used Vec3
before, including as a constructor:
let c = Color(0.5, 0.5, 1.0);
I don’t think this is common in Rust though -- that’s not what the use
keyword is meant
for. I’m just mentioning it here for completeness.
The limitation of type aliases is that they don’t provide any extra type safety. Defining Color as
an alias for Vec3 won’t stop you from accidentally calling a function expecting a Color with a Vec3
that represents a point in 3D space. If that’s what you’re looking for, you need the newtype
pattern. (The name comes from Haskell, I think, which has a newtype
keyword that does
the same thing.)
The idea is to define a new type as a tuple struct with a single element, so it’s basically a wrapper for another type:
struct Meters(f64);
struct Feet(f64);
Now if you try to assign a value of type Meters to a variable of type Feet, the compiler will stop you. The downside is that all the operators and methods of f64 won’t work on Meters and Feet, so you may have to write a lot of repetitive code to do things like add two values of type Meter.