Rust Indexed Access Types (e.g. type Asdf = MyStruct::field)

Viewed 35

Is there a way to define a type in terms of the type of a field of a struct in Rust?

Such as:

struct Person {
   id: i32,
}

type PersonId = Person::id;

(I know that I could define PersonId as i32 and make Person use that, but I am not interested in this use case. My particular use case is code-generation, so it would help if my Rust outputs are more similar to the other input language.)

TypeScript has an analogous concept, if this helps explain what I am asking for: https://www.typescriptlang.org/docs/handbook/2/indexed-access-types.html

1 Answers

One way to achieve this would be through the use of associated types.

One gotcha is that you need a trait to define an associated type. In your case, such a trait could be an Identifiable:

trait Identifiable {
    type Id;

    fn id(&self) -> Self::Id;
}

Your structure would implement said trait:

struct Person {
   id: i32,
}

impl Identifiable for Person {
    type Id = i32;

    fn id(&self) -> Self::Id {
        self.id
    }
}

type PersonId = <Person as Identifiable>::Id;

It could be used like this:

let id: PersonId = 23;
let person = Person { id };

As per the documentation, the reason that we cannot simply use Person::Id is that Person might implement two different traits with identically-named associated types. This syntax allows disambiguation between the two.

Interestingly, as the associated type is defined in a trait, it's entirely possible to define the struct's field type as the alias that's specified below it.

It is therefore legal to write:

struct Person {
   id: PersonId, // ---> instead of i32
}

See it in action in the playground.

Related