Как получить автоматическое соответствие 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
}

0 ответов

Другие вопросы по тегам