Extending Types

Two ways to shape types from outside their definition: extensions add behavior, type aliases name something that already exists.

Extensions

extend adds methods, computed variables, or protocol conformance to any type — including types you didn't define:

extend Array[Int] { func sum() -> Int { var total = 0; for n in self { total = total + n; } total } } let total = [1, 2, 3].sum(); // 6

This works on stdlib types, your own types, and types from third-party modules. The extension lives in whatever file declares it; everywhere that file is imported, sum() is available on Array[Int].

You can also add conformance through an extension:

struct Point { let x: Int let y: Int } extend Point: Equatable { public func isEqual(to other: Point) -> Bool { self.x == other.x and self.y == other.y } } let same = Point(x: 1, y: 2) == Point(x: 1, y: 2); // true

Anywhere a function takes an Equatable, your Point now works.

If the protocol you're conforming to is generic, its type arguments can introduce free type parameters on the conformance line — no keyword-side declaration:

protocol Tagger[T] { type Tagged func tag(with value: T) -> Tagged } extend Int64: Tagger[T] { type Tagged = (Int64, T) public func tag(with value: T) -> (Int64, T) { (self, value) } } let pair = 3.tag(with: "bronze"); // (3, "bronze")

T is bound by the conformance, not by Int64. Reads as "for all T, Int64 conforms to Tagger[T]" — the stdlib uses the same shape to make Int64 index any Array[T].

For protocol-side extensions (adding behavior to all conformers of a protocol), see Protocols → Extending.

Type aliases

A type alias gives a new name to an existing type:

struct Request { let path: String } struct Response { let status: Int } public type UserId = Int public type Handler = (Request) -> Response public type StringDict[V] = Dictionary[String, V]

Aliases are not new types — they're just names. UserId is Int, with all the same methods and constraints. Don't reach for an alias when you want a distinct type with different rules; use a struct:

// distinct from Int — can't accidentally pass a row count where a UserId is expected struct UserId { let raw: Int }

The two together are powerful: aliases for "this is a kind of Int we use a lot," structs for "this is a different thing that happens to be wrapped around an Int."