type による型の別名 (エイリアス) の定義方法について。

用例

以下は代表的な用例。

用例 1

基本的な使い方

type Alias = SomeType; とする事で、型 SomeType の別名 Alias を定義できる。

サンプル

以下では、Vec<f32>MyVec の別名を定義している。


fn main() {
    let v = vec![3.0, 2.0];
    println!("v = {}", get_vec_str(v));
}

type MyVec = Vec<f32>;

fn get_vec_str(v: MyVec) -> String {
    let texts = v.iter().map(f32::to_string);
    format!("({})", texts.collect::<Vec<_>>().join(", "))
}

用例 2

型パラメタの利用

別名には型パラメタを含める事ができる。

サンプル

以下では、二つの同じ型からなるタプルを Pair<T> として定義している。


fn main() {
    let pair = (40, 20);
    println!("pair = {}", get_pair_str(pair));
}

type Pair<T> = (T, T);

fn get_pair_str(p: Pair<i32>) -> String {
    format!("({}, {})", p.0, p.1)
}

用例 3

関連型の導出

型パラメタから関連型を導出する型の関数としても利用できる。

サンプル

以下では、nth1nth2 は全く同じ機能になる。


fn main() {
    let samples = vec![1, 2, 3];
    let item1 = nth1(samples.iter(), 2);
    let item2 = nth2(samples.iter(), 2);
    assert_eq!(item1, item2);
}

type ToItem<T> = <T as Iterator>::Item;

fn nth1<I: Iterator>(mut iter: I, n: usize) -> Option<I::Item> {
    iter.nth(n)
}

fn nth2<I: Iterator>(mut iter: I, n: usize) -> Option<ToItem<I>> {
    iter.nth(n)
}

注意点

注意点 1

別名の互換性

type エイリアスによる別名は、新しい型として作られるわけではない。そのため、元の型や同じように作られた別名と良くも悪くも互換性がある (取り違えを防ぐ目的では、Newtype パターンが利用可能)。

サンプル

以下では、f32 に別名 LengthTime を定義しているが、それらを取り違えている。


fn main() {
    let length = 4000.0;
    let time = 3600.0;
    println!("speed = {}", speed(time, length));
}

type Length = f32;
type Time = f32;

fn speed(l: Length, t: Time) -> f32 {
    l / t
}

注意点 2

初期化関数は利用不可

type エイリアスは型の別名を作るだけで、関数の別名までは作らない。そのため、タプルや構造体の別名を作っても、その初期化用関数の別名までは作られない。なお、use Type as Alias; での別名ではこれができる (ただし、こちらは型パラメタの利用に制限がある)。

サンプル

以下では、型 Color の別名 Rgb を定義しているが、初期化に別名は使えない。


fn main() {
    let gray = Color(0x80, 0x80, 0x80);
    let blue = Triple(0x00, 0x00, 0xFF);
	let aqua = Rgb(0x00, 0xFF, 0xFF);
    println!("gray = {}", get_color_str(gray));
    println!("blue = {}", get_color_str(blue));
    println!("aqua = {}", get_color_str(aqua));
}

struct Color(u8, u8, u8);
use Color as Triple;
type Rgb = Color;

fn get_color_str(color: Color) -> String {
    format!("#{:02X?}{:02X?}{:02X?}", color.0, color.1, color.2)
}

error[E0423]: expected function, tuple struct or tuple variant, found type alias `Rgb`
 --> src\main.rs:4:16
  |
4 |     let aqua = Rgb(0x00, 0xFF, 0xFF);
  |                ^^^
  |
  = note: can't use a type alias as a constructor

注意点 3

where は利用不可

type エイリアスの型パラメタは where で制限できない (エラーメッセージの note を見ると、GitHub へのリンクがあるので将来は変更されるかも…?)。

サンプル


use std::fmt::Display;

fn main() {
    let pair = (40, 20);
    println!("pair = {}", get_pair_str(pair));
}

type Pair<T> = (T, T) where T: Display;

fn get_pair_str<T: Display>(p: Pair<T>) -> String {
    format!("({}, {})", p.0, p.1)
}

error: where clauses are not allowed after the type for type aliases
 --> src\main.rs:8:23
  |
8 | type Pair<T> = (T, T) where T: Display;
  |                       ^^^^^^^^^^^^^^^^
  |
  = note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information