Можно ли аннотировать ключ словаря?

У меня есть следующий словарь:

let myDict: [String: Any] = [
  "first": [
    "message": "qqq",
    "extras": ["task": "first"]
  ],
  "second": [
    "message": "www",
    "extras": ["task": "second"]
  ],
  "third": [
    "message": "eee",
    "extras": ["task": "third"]
  ],
]

Обратите внимание, как это обозначено как [String: Any]. Тем не менее, Swift, похоже, жалуется, что сами ключи не аннотированы:

/tmp/example.swift:2:12: warning: heterogeneous collection literal could only be inferred to '[String : Any]'; add explicit type annotation if this is intentional
  "first": [
           ^
/tmp/example.swift:6:13: warning: heterogeneous collection literal could only be inferred to '[String : Any]'; add explicit type annotation if this is intentional
  "second": [
            ^
/tmp/example.swift:10:12: warning: heterogeneous collection literal could only be inferred to '[String : Any]'; add explicit type annotation if this is intentional
  "third": [
           ^

Можно ли вообще аннотировать ключи словаря? Что удовлетворило бы Свифта в этой ситуации?

[String: [String: Any]] можно?
Larme 04.04.2023 23:57

Кажется, это работает для меня без каких-либо предупреждений. Это может быть какая-то проблема с общими скобками или что-то в этом роде. Можете ли вы поделиться всем файлом здесь?

nutz 05.04.2023 00:34

@nutz Обновите свой Xcode.

matt 05.04.2023 00:36
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
3
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы неправильно читаете предупреждение. Компилятор говорит о значении, а не о ключе. Проблема в том, что эти значения сами по себе являются разнородными словарями:

[
  "message": "qqq",
  "extras": ["task": "first"]
]

Это словарь со строковыми ключами, но значениями двух разных типов. Таким образом, это [String: Any]. Итак, вам нужно сказать, что:

let myDict: [String: [String: Any]] = [

В качестве альтернативы вы можете записать это в общей нотации:

let myDict: Dictionary<String, Dictionary<String, Any>> = [

Может показаться, что компилятор здесь излишне придирчив, но идея в том, что ранее компилятор делал предположение, пытаясь вывести здесь тип, и получение такого предположения дорого обходится. На самом деле вывод типов стоит дорого, за исключением самых простых случаев. Литералы массивов и словарей всегда стоит аннотировать явно, потому что в противном случае компилятору придется просматривать каждый отдельный элемент. (Если их достаточно, компилятор сдастся с жалобой на то, что он не может вывести тип за разумное время; возможно, вы видели эту ошибку.) Таким образом, чем больше времени вы можете потратить на аннотирование ваших типов, тем что компилятору не нужно их выводить, тем быстрее ваше приложение будет компилироваться в Xcode.

Для полноты предупреждение, показанное в Xcode, имеет «исправление», которое изменит строку на "first": [ "message": "qqq", "extras": ["task": "first"]] as [String: Any]. Четко объявить myDict: [String: [String: Any]] лучше.

HangarRash 05.04.2023 00:44

Спасибо за подробное объяснение. Просто чтобы было абсолютно ясно, вы говорите, что этот удар по производительности влияет только на время компиляции, а не на время выполнения, верно? Я буду иметь это в виду. Я делал небольшие CLI-приложения, так что это пока не проблема.

user137369 05.04.2023 01:25

Да, но лучше завести хорошие привычки. И независимо от производительности Swift движется к отмене «случайного Any». Это предупреждение будет ошибкой в ​​Swift 6. Итак, давайте будем готовы.

matt 05.04.2023 02:07

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