Enforce any existential to have a value conforming to a certain protocol

About

I would like to be able to enforce that some existential conforms to a specific protocol. This question relates to an existing package I am developing, which uses a sub-par solution, due to reduced compile time safety as I haven't found a way to express this within the Swift type system.

This post will use a SwiftUI example for demonstration purposes to give more context, but this is not dependent on SwiftUI. This post is a very simplied version of the problem I'm having.

Aim

I aim to have my package have full safety enforced by the type system. I will refer to the user side of the package as the "client". Requirements:

  1. The code in the framework should not (and will not) have access to protocols defined by the client.
  2. We use type safety instead of runtime checks.

Below is some code of what I expect the result to look like:

import SwiftUI


// Package
struct Tree<ID: Hashable>: View {
    @Binding private var element: any Identifiable<ID>

    init(element: Binding<any Identifiable<ID>>) {
        _element = element
    }

    var body: some View {
        Text("ID: \(element.id)")
    }
}


// Client
protocol MyElement: Identifiable<UUID> {}

struct El1: MyElement {
    let id = UUID()
}
struct El2: MyElement {
    let id = UUID()
}

struct ContentView: View {
    @State private var element: any MyElement = El1()

    var body: some View {
        Tree(element: $element)
    }
}

This gives the following errors in the ContentView body:

Cannot convert value of type 'Binding' to expected argument type 'Binding<any Identifiable>'

Generic parameter 'ID' could not be inferred

Explicitly specifying the ID fixes the second error, but still not the first.

Current solution

We've seen what I aim for. Here's what I currently have, which does in fact work:

import SwiftUI


// Package
struct Tree<ID: Hashable>: View {
    @Binding private var element: any Identifiable<ID>

    init<T>(element: Binding<T>) {
        precondition(element.wrappedValue is any Identifiable<ID>, "Element is of wrong type")

        _element = Binding(
            get: { element.wrappedValue as! any Identifiable<ID> },
            set: { element.wrappedValue = $0 as! T }
        )
    }

    var body: some View {
        Text("ID: \(element.id)")
    }
}


// Client
protocol MyElement: Identifiable<UUID> {}

struct El1: MyElement {
    let id = UUID()
}
struct El2: MyElement {
    let id = UUID()
}

struct ContentView: View {
    @State private var element: any MyElement = El1()

    var body: some View {
        Tree<UUID>(element: $element)
    }
}

It has several downsides:

  1. The ID type is explicitly required, even though MyElement defines the ID.
  2. Any type can be used in place of T, and so the precondition only catches issues at run time.

Solution

What's the solution to this? Does it currently exist within the Swift type system to express that an any existential should have a value conforming to a certain protocol?