Как получить автоматическое соответствие Encodable свойству массива, но без использования дженериков?
Я хотел бы определить структуру с автоматическим соответствием Encodable, где структура имеет массив элементов Encodable:
struct EncodableBagB: Encodable {
var values: [Encodable] // ❌ Type 'EncodableBagB' does not conform to protocol 'Encodable'
}
Если мы сделаем шаг назад и не будем использовать массив, способ решить эту проблему — переместить Encodable в общий вид:
struct EncodableBagA1<T: Encodable>: Encodable {
var value: T // Okay, but doesn't work for arrays
}
Если я сделаю то же самое с массивом, я потеряю возможность хранить разнородные элементы:
struct EncodableBagB1<T: Encodable>: Encodable {
var values: [T]
}
EncodableBagB1(values: ["A", "B"])
EncodableBagB1(values: ["A", "B", 1]) // ❌ Type of expression is ambiguous without more context
Единственный обходной путь, кажется, состоит в том, чтобы ввести массу повторяющихся общих структур:
struct EncodableBagB1_2<T0: Encodable, T1: Encodable, T2: Encodable, T3: Encodable>: Encodable {
var value0: T0
var value1: T1
var value2: T2
var value3: T3
init(_ encodable0: T0, _ encodable1: T1, _ encodable2: T2, _ encodable3: T3) {
value0 = encodable0
value1 = encodable1
value2 = encodable2
value3 = encodable3
}
// Okay, but very verbose and requires a bunch of duplicate structures (e.g. T0, T0-1, T0-2, T0-3, etc.) for each permutation
}
Может Swift 5.7some
илиany
ключевые слова помогают в этой ситуации, или есть ли какие-либо предстоящие предложения, которые в конечном итоге решат эту проблему? Как называется эта проблема (чтобы я знал, что искать в будущем)?
Я бы предпочел избегать стирания ручного типа (например,AnyEncodable
) если возможно, так как я хотел бы использоватьMirror
на элементы внутри массива.
Примечание: я используюEncodable
чтобы упростить пример. Фактический протокол, который я в конечном итоге использую, выглядит примерно так:protocol Foo: Encodable { func bar() }
.
Вот исчерпывающий список всего, что я пробовал:
// MARK: Single value
struct EncodableBagA: Encodable {
var value: Encodable // ❌ Type 'EncodableBagA' does not conform to protocol 'Encodable'
}
struct EncodableBagA1<T: Encodable>: Encodable {
var value: T // Okay, but doesn't work for arrays
}
struct EncodableBagA2: Encodable { // ❌ Type 'EncodableBagA2' does not conform to protocol 'Encodable'
var value: any Encodable
}
struct EncodableBagA3: Encodable {
var value: some Encodable // ❌ Property declares an opaque return type, but has no initializer expression from which to infer an underlying type
}
// MARK: Array
struct EncodableBagB: Encodable { // ❌ Type 'EncodableBagB' does not conform to protocol 'Encodable'
var values: [any Encodable]
}
struct EncodableBagB1<T: Encodable>: Encodable {
var values: [T]
}
EncodableBagB1(values: ["A", "B"])
EncodableBagB1(values: ["A", "B", 1]) // ❌ Type of expression is ambiguous without more context
struct EncodableBagB2<T: Encodable>: Encodable {
var values: [any T] // ❌ 'any' has no effect on type parameter 'T'
}
struct EncodableBagB3<T: Encodable>: Encodable { // ❌ Type 'EncodableBagB3' does not conform to protocol 'Encodable'
var values: [some T] // ❌ An 'opaque' type must specify only 'Any', 'AnyObject', protocols, and/or a base class
}
struct EncodableBagB1_1<T0: Encodable, T1: Encodable, T2: Encodable, T3: Encodable>: Encodable {
var value0: T0
var value1: T1
var value2: T2
var value3: T3
init(_ encodables: Encodable...) {
value0 = encodables[0] // ❌ Cannot assign value of type 'any Encodable' to type 'T0'
value1 = encodables[1] // ❌ Cannot assign value of type 'any Encodable' to type 'T1'
value2 = encodables[2] // ❌ Cannot assign value of type 'any Encodable' to type 'T2'
value3 = encodables[3] // ❌ Cannot assign value of type 'any Encodable' to type 'T3'
}
}
struct EncodableBagB1_2<T0: Encodable, T1: Encodable, T2: Encodable, T3: Encodable>: Encodable {
var value0: T0
var value1: T1
var value2: T2
var value3: T3
init(_ encodable0: T0, _ encodable1: T1, _ encodable2: T2, _ encodable3: T3) {
value0 = encodable0
value1 = encodable1
value2 = encodable2
value3 = encodable3
}
// Okay, but very verbose and requires a bunch of duplicate structures (e.g. T0, T0-1, T0-2, T0-3, etc.) for each permutation
}