Dart — как заставить ключ карты содержаться в строках списка

#typescript #dart

#typescript #dart

Вопрос:

Допустим, у меня есть следующая карта, которая имеет key1 и key2 :

 Map<String, bool> _map = {
  'dog': true,
  'cat': true
};
  

Теперь я хочу принудительно использовать Dart, чтобы разрешить только определенный из ключей. В Typescript я мог бы сделать что-то вроде:

 enum AvailableKeysEnum {
  Dog = 'dog',
  Cat = 'cat'
}

interface AvailableKeys {
  [key in AvailableKeysEnum]: boolean;
}

const availableKeys: AvailableKeys = {
  'dog': true, // Allowed
  'cat': true, // Allowed
  'dolphin': true // Denied
}
  

Мой вопрос в том, как я могу заставить Dart разрешить только определенные ключи?

Комментарии:

1. На самом деле нет способа сделать это в Dart (пока), за исключением, возможно, создания пользовательской реализации карты, что не слишком сложно (используя api.dartlang.org/stable/2.2.0/dart-collection /… ) но, вероятно, все равно не стоит.

2. Dart и Typescript — очень разные языки. Typescript имеет структурную систему типов. Это позволяет использовать такие функции в Typescript. Система структурных типов (или система типов на основе свойств) — это основной класс систем типов, в котором совместимость типов и эквивалентность определяются фактической структурой или определением типа, а не другими характеристиками, такими как его имя или место объявления.

Ответ №1:

Если я правильно понял (я не знаю TypeScript)

У Dart нет ключевых ограничений, поэтому придется расширить карту и реализовать эти ограничения. Вот код для этого.

 import 'dart:collection';

class InvalidKeyError<K> extends Error {
  final Object key;
  final Set<K> keys;

  InvalidKeyError(this.key, this.keys);

  @override
  String toString() => "InvalidKeyError: $key not found in $keys";
}

class SpecialMap<K, V> extends MapMixin<K, V> {
  final Set<K> availableKeys;

  final Map<K, V> _map = {};

  SpecialMap(this.availableKeys) : assert(availableKeys != null);

  @override
  Iterable<K> get keys => _map.keys;

  @override
  void clear() => _map.clear();

  @override
  V remove(Object key) => _map.remove(key);

  @override
  V operator [](Object key) => availableKeys.contains(key)
      ? _map[key]
      : throw InvalidKeyError(key, availableKeys);

  @override
  operator []=(K key, V value) => availableKeys.contains(key)
      ? _map[key] = value
      : throw InvalidKeyError(key, availableKeys);
}

void main() {
  final availableKeys = {"cat", "dog"};
  final map = SpecialMap<String, bool>(availableKeys);

  map["cat"] = true;
  map["dog"] = true;
  map["anything else"] = false; //will throw InvalidKeyError at runtime
}
  

Хотя вы можете просто ограничить через type, если хотите. Что-то вроде этого.

 enum Keys {cat, dog}

void main(){
  final Map<Keys, bool> map = {};
  map[Keys.cat] = true;
  map[Keys.dog] = true;
  map["any other type"] = false; //complie time error
}
  

Комментарии:

1. отметьте ansert как правильное решение, пожалуйста, если это то, что вы искали.