In Rust, the newtype idiom wraps an underlying types with another type to enforce correct usage. E.g.
struct Years(i64);
struct Days(i64);
impl Days {
/// truncates partial years
pub fn to_years(&self) -> Years {
Years(self.0 / 365)
}
}
The newtype idiom can also be a useful way to circumvent the orphan rule.
Newtype Index
We can implement std::ops::Index
for newtype indices 1. We can even implement multiple std::ops::Index<T>
for different types, which is convenient for holding distinct types:
struct World {
foos: Vec<Foo>,
bars: Vec<Bar>,
}
impl ops::Index<FooIdx> for Arena { ... }
impl ops::Index<BarIdx> for Arena { ... }
Conversions
see: Rust conversions
We can implement From
or TryFrom
to convert from primitives to newtype. And AsRef
is useful to implement for code to consume new types as primitives.
See Also
Related Ideas in other Langauges
- C++ people talks about a similar “strongly-typed alias” idiom
- Programming languages like Odin has a “distinct types” feature
- primitive obsession