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