Skip to content

Dynamic Member Lookup (Swift)

A SwiftUI guide for coding agents. Also covers dynamicmemberlookup attribute, keypath subscript, dot syntax passthrough, store state access, forward properties to wrapped type, dynamic member subscript.

@dynamicMemberLookup lets a type answer dot syntax for members it does not declare, by routing the access through a subscript(dynamicMember:). Use it to make a wrapper type read like the type it wraps.

String-Based Lookup

The string form turns any member name into a subscript key at runtime.

@dynamicMemberLookup
struct Cache {
    private var storage: [String: Data] = [:]

    subscript(dynamicMember key: String) -> Data? {
        storage[key]
    }
}

var cache = Cache()
let profile = cache.profile   // storage["profile"]

The cost is compile-time safety: every name compiles, and the result is whatever your subscript decides at runtime. Any misspelling still builds.

KeyPath-Based Lookup

The KeyPath form keeps the ergonomics and restores the compiler check. A store can expose its private state read-only, member by member.

@dynamicMemberLookup
final class Store<State, Action>: ObservableObject {
    @Published private var state: State
    private let reduce: (State, Action) -> State

    init(initialState state: State, reduce: @escaping (State, Action) -> State) {
        self.state = state
        self.reduce = reduce
    }

    subscript<T>(dynamicMember keyPath: KeyPath<State, T>) -> T {
        state[keyPath: keyPath]
    }

    func send(_ action: Action) {
        state = reduce(state, action)
    }
}

Only key paths rooted in State compile, so a wrong member is a compiler error, not a runtime surprise.

print(store.isLoading)   // fine, State.isLoading
print(store.favorites)   // compiler error: State has no favorites

The state stays private, so callers read through the store but can only mutate through send(_:).

Use this guidance in your coding agent

Install the Better Design MCP once. Your agent then loads this page with one call.

get-swiftui-guide({ topic: "swiftui-dynamic-member-lookup-in-swift" })
claude mcp add --scope user better-design --transport http https://better-design.com/api/mcp --header "Authorization: Bearer <YOUR_API_KEY>"
Browse related design systems