Dart TypeError: тип не является подтипом типа «Никогда»

Я озадачен тем, почему следующий код Dart генерирует ошибку времени выполнения:

class Store<ID, T> {
  Store({Map<ID, T> values = const {}}) : _cache = values;

  final Map<ID, T> _cache;

  void put(ID id, T value) {
    _cache[id] = value;
  }
}

...
final foo = Store<int, Store<int, String>>();

// Runtime error inside `Store.put`:
// TypeError: 7: type 'int' is not a subtype of type 'Never'
foo.put(7, Store<int, String>());

Это не проблема, если я использую Map прямо так:

final foo = Map<int, Map<int, String>>();
foo[7] = Map<int, String>());

Есть ли что-то, что мне нужно понять в дженериках Dart, чтобы Store работало?

«Никогда» означает, что функция никогда не возвращается, например, она завершает процесс или всегда выдает исключение. nagaraj.com.au/blog/what-is-never-in-dart Что такое удостоверение личности? Попробуйте не указывать идентификатор, возможно, он сгенерирован автоматически.

M H 08.05.2024 05:33

Просто хотел упомянуть, что _cache скорее должен быть копией values, например: Store({Map<ID, T> values = const {} }) : _cache = Map.of(values); В противном случае пользователь может сохранить ссылку на values и случайно изменить приватную переменную _cache.

Dan R 08.05.2024 18:53

Спасибо, @DanR! Я предполагал, что это копирование в независимую переменную Map. Похоже, есть семантика языка Dart, которую мне нужно лучше понять.

Kris Braun 08.05.2024 23:47

Я не добавлял это явно в своем предыдущем комментарии, но эта настройка также устраняет ошибку во время выполнения.

Dan R 09.05.2024 09:04
2
4
81
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я считаю, что это было вызвано const {}, потому что оно имеет тип Map<Never, Never>

Вы можете попробовать это:

class Store<ID, T> {
  Store() : _cache = {};

  final Map<ID, T> _cache;

  void put(ID id, T value) {
    _cache[id] = value;
  }
}
Ответ принят как подходящий

Если вы наведете курсор на const {} в редакторе, вы увидите Type: Map<Never, Never>. В любом случае вы не можете использовать здесь карту const, потому что вы не можете изменять карту const. Вы можете назначить _cache непостоянную карту в списке инициализаторов.

class Store<ID, T> {
  Store({Map<ID, T>? values}) : _cache = values ?? {};

  final Map<ID, T> _cache;

  void put(ID id, T value) {
    _cache[id] = value;
  }
}

Спасибо. Требование, чтобы аргументы по умолчанию были const, подтолкнуло меня к этому, поэтому ключевым моментом была техника сделать аргумент необязательным и поместить значение по умолчанию в список инициализаторов.

Kris Braun 08.05.2024 14:22

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