The type
keyword lets you declare an alias of another type:
type Name = String;
You can then use this type as if it were a real type:
fn main() { type Name = String; let x: Name = "Hello".to_string(); }type Name = String; let x: Name = "Hello".to_string();
Note, however, that this is an alias, not a new type entirely. In other words, because Rust is strongly typed, you’d expect a comparison between two different types to fail:
fn main() { let x: i32 = 5; let y: i64 = 5; if x == y { // ... } }let x: i32 = 5; let y: i64 = 5; if x == y { // ... }
this gives
error: mismatched types:
expected `i32`,
found `i64`
(expected i32,
found i64) [E0308]
if x == y {
^
But, if we had an alias:
fn main() { type Num = i32; let x: i32 = 5; let y: Num = 5; if x == y { // ... } }type Num = i32; let x: i32 = 5; let y: Num = 5; if x == y { // ... }
This compiles without error. Values of a Num
type are the same as a value of
type i32
, in every way. You can use tuple struct to really get a new type.
You can also use type aliases with generics:
fn main() { use std::result; enum ConcreteError { Foo, Bar, } type Result<T> = result::Result<T, ConcreteError>; }use std::result; enum ConcreteError { Foo, Bar, } type Result<T> = result::Result<T, ConcreteError>;
This creates a specialized version of the Result
type, which always has a
ConcreteError
for the E
part of Result<T, E>
. This is commonly used
in the standard library to create custom errors for each subsection. For
example, io::Result.