Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Rust Dictionary

  1. Home
  2. Rust Dictionary
  3. Type Aliases (type) / Newtype Pattern

Type Aliases (type) / Newtype Pattern

Since: Rust 1.0(2015)

In Rust, you can use the type keyword to create an alias for an existing type, or use the newtype pattern — wrapping a type in a tuple struct — to improve type safety.

Syntax

type Kilometers = i32;
type Result<T> = std::result::Result<T, String>;
type Callback = Box<dyn Fn(i32) -> i32>;

// Newtype pattern — wraps a type in a tuple struct.
struct Meters(f64);
struct Kilograms(f64);

// Implement From / Display for the newtype.
impl From<f64> for Meters {
    fn from(val: f64) -> Self { Meters(val) }
}

// Extract the inner value from the newtype.
let m = Meters(5.0);
let val: f64 = m.0; // Field access on a tuple struct

Concepts

FeatureDescription
type aliasAn alternative name for an existing type. Type checking treats it identically to the original type. Useful for shortening long type names.
Newtype patternWraps a type in a tuple struct. Improves type safety by turning incorrect assignments into compile errors.
Newtype + DerefImplementing the Deref trait lets you transparently call methods of the inner type.
type T = ... (generics)You can create an alias that fixes some type parameters of a generic type (partially applied alias).
Preventing unit mixingMaking Meters and Kilometers distinct types prevents bugs caused by accidentally mixing units.

Sample Code

sample_type_alias_newtype.rs
use std::fmt;
use std::ops::Add;

// Type alias examples
type Thunk = Box<dyn Fn() -> String>;
type Point2D = (f64, f64);
type StrResult<T> = Result<T, String>;

// Newtype pattern — represent units as distinct types.
#[derive(Debug, Clone, Copy, PartialEq)]
struct Meters(f64);

#[derive(Debug, Clone, Copy, PartialEq)]
struct Kilograms(f64);

impl Meters {
    fn new(val: f64) -> Self { Meters(val) }
    fn value(&self) -> f64 { self.0 }
}

// Implement the Add trait.
impl Add for Meters {
    type Output = Meters;
    fn add(self, other: Meters) -> Meters {
        Meters(self.0 + other.0)
    }
}

// Implement the Display trait.
impl fmt::Display for Meters {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}m", self.0)
    }
}

// Implement the From trait.
impl From<f64> for Meters {
    fn from(val: f64) -> Self { Meters(val) }
}

fn total_distance(a: Meters, b: Meters) -> Meters {
    a + b
}

fn main() {
    // Type aliases
    let point: Point2D = (3.0, 4.0);
    println!("point: {:?}", point);

    let greet: Thunk = Box::new(|| String::from("Hello!"));
    println!("{}", greet());

    // Using StrResult.
    let ok: StrResult<i32> = Ok(42);
    let err: StrResult<i32> = Err(String::from("error"));
    println!("ok: {:?}, err: {:?}", ok, err);

    // Using the newtype
    let dist1 = Meters::new(100.0);
    let dist2 = Meters::new(250.5);
    let total = total_distance(dist1, dist2);
    println!("Total distance: {}", total); // 350.5m

    // The newtype prevents accidental assignments.
    let weight = Kilograms(75.0);
    // total_distance(dist1, weight); // Compile error! Mismatched types.
    println!("Weight: {:?}", weight);

    // Accessing the inner value
    println!("dist1 value: {}", dist1.value()); // 100

    // Newtype + From trait
    let m: Meters = 50.0_f64.into();
    println!("into(): {}", m); // 50m
}

Compile with the following command:

rustc type_alias_newtype.rs
./type_alias_newtype
point: (3.0, 4.0)
Hello!
ok: Ok(42), err: Err("Error")
Total distance: 350.5m
Weight: Kilograms(75.0)
dist1 value: 100
into(): 50m

Common Mistakes

Mistake 1: Assuming a type alias provides type safety

A type alias (type) is just another name for the same underlying type. Mixing up units is not detected by the type checker. Use the newtype pattern when type safety is needed.

type_alias_mistake1.rs
type Meters = f64;
type Kilograms = f64;

fn calculate_bmi(weight: Kilograms, height: Meters) -> f64 {
    weight / (height * height)
}

fn main() {
    let height: Meters = 1.75;
    let weight: Kilograms = 70.0;

    // Swapping the arguments does not cause a compile error (both are f64).
    let bmi = calculate_bmi(height, weight); // Wrong argument order
    println!("BMI: {:.2}", bmi); // Incorrect value is printed.
}

Compile with the following command:

rustc type_alias_mistake1.rs
./type_alias_mistake1
BMI: 0.00

With the newtype pattern, swapping the arguments causes a compile error.

type_alias_fix1.rs
#[derive(Debug, Clone, Copy)]
struct Meters(f64);

#[derive(Debug, Clone, Copy)]
struct Kilograms(f64);

fn calculate_bmi(weight: Kilograms, height: Meters) -> f64 {
    weight.0 / (height.0 * height.0)
}

fn main() {
    let height = Meters(1.75);
    let weight = Kilograms(70.0);

    // Swapping the arguments causes a compile error.
    // calculate_bmi(height, weight); // error: mismatched types

    let bmi = calculate_bmi(weight, height);
    println!("BMI: {:.2}", bmi); // 22.86
}

Compile with the following command:

rustc type_alias_fix1.rs
./type_alias_fix1
BMI: 22.86

Mistake 2: Forgetting .0 when accessing the inner value of a newtype

To access the inner value of a newtype tuple struct, use .0. Trying to use the struct directly in an arithmetic expression causes a compile error.

type_alias_mistake2.rs
struct Meters(f64);

fn main() {
    let m = Meters(100.0);

    // Using m directly in arithmetic causes a compile error.
    // let doubled = m * 2.0; // Compile error

    // Use .0 to extract the inner value.
    let doubled = m.0 * 2.0;
    println!("doubled: {}", doubled); // 200

    // Alternatively, implement Add to enable arithmetic operators.
    // (See the Add implementation in sample_type_alias_newtype.rs)
}

Compile with the following command:

rustc type_alias_mistake2.rs
./type_alias_mistake2
doubled: 200

Overview

A type alias (type) is used to shorten long type names. Because type checking treats the alias identically to the original type, it does not improve type safety — it is purely a readability convenience.

The newtype pattern wraps a type in a tuple struct to prevent type mixing at compile time. For example, Meters and Kilograms are treated as distinct types, so passing the wrong one as an argument becomes a compile error. The newtype pattern is also useful for implementing additional traits on types from external crates (working around the orphan rule).

For implementing conversion traits, see From / Into / TryFrom / TryInto Traits. For numeric type casting, see as Cast / Numeric Type Conversion.

If you find any errors or copyright issues, please .