Strictly speaking, the Codable protocol doesn't either. Instead the machinery that provides the Codable conformance synthesis only works if all the stored properties are also Codable. But you can absolutely have a Codable struct with non-Codable fields if you implement the conformance yourself.
I was going to say the same, and add that Equatable and Hashable behave the same way: you can get a default synthesized implementation which can be created if all of your properties are Equatable/Hashable, but there's nothing about these protocols which inherently requires that this be true.
Depending on the specifics of what exactly you're looking to do in the general case, you could theoretically introduce a protocol with an associatedtype requirement which requires conformance of that type to AppEvent, and then have Person conform to that protocol — but it doesn't sound likely that this is what you want, since presumably you'd need to scale this to multiple properties.
Otherwise, this isn't possible in the language itself: Equatable, Hashable, and Codable all require compiler support to make their default implementations possible, because the behavior can't be expressed within Swift itself yet.
One non ideal option would be to force "AppEvent" requirement on all types you store in "AppEvent" types (including Strings, Ints, etc):
let appEvent = tuple.value as! AppEvent
then the first call to dictionary (which could be as early as its init) would result a runtime crash if the type has children that do not adhere to AppEvent. Unfortunately this is a runtime check, not a compile time check, although might be better than nothing. Other than that, unit testing would help to catch such mistakes.
Your yet is promising
Bike shedding how it could look (pseudo code):
/// Built-in protocol
protocol CompileTimeCheck {
static func compileTimeCheck() throws
}
protocol AppEvent: CompileTimeCheck {
static func compileTimeCheck() throws {
let mirror = Mirror(forType: Self)
check children here
if something is wrong {
throw "Property \(child) doesn't conform to AppEvent"
}
}
}
struct S: AppEvent { // Error: "Property `gender` doesn't conform to AppEvent"
var gender: Gender
}