ambiguous_set_or_map_literal_both 진단: map과 set 리터럴을 둘 다 만들 수 없을 때

ambiguous_set_or_map_literal_both 진단: map과 set 리터럴을 둘 다 만들 수 없을 때

Dart 분석기가 내보내는 진단에는 이름이 있어요. ambiguous_set_or_map_literal_both한 리터럴 안에 map 리터럴 요소와 set 요소가 섞여 있어서 map인지 set인지 정할 수 없을 때 분석기가 알려주는 컴파일 타임 진단이에요.

출처: ambiguous_set_or_map_literal_both

본문

설명

map 리터럴과 set 리터럴은 같은 구분 기호({})를 쓰기 때문에, 분석기는 타입 인자와 요소들을 보고 어느 쪽 리터럴인지 판단해요. 타입 인자가 없으면 요소들의 타입을 사용해요. 모든 요소가 리터럴 map 항목이고 모든 전개 연산자가 Map을 전개한다면 Map이에요. 요소 중 리터럴 map 항목이 하나도 없고 모든 전개 연산자가 Iterable을 전개한다면 Set이에요. 둘 다 아니라면 모호해요.

분석기는 어떤 요소는 리터럴 map 항목이거나 Map을 전개하는 전개 연산자이고, 어떤 요소는 그중 하나도 아니어서, map 리터럴을 쓰는 건지 set 리터럴을 쓰는 건지 결정할 수 없을 때 이 진단을 만들어요.

예시

다음 코드는 이 진단을 만들어요.

union(Map<String, String> a, List<String> b, Map<String, String> c) => {
  ...a,
  ...b,
  ...c,
};

리스트 b는 set에만 전개할 수 있고, map ac는 map에만 전개할 수 있어서, 이 리터럴은 둘 다가 될 수 없어요.

흔한 해결 방법

이 문제를 고치는 흔한 방법은 두 가지예요. 첫 번째는 어느 한 종류의 전개 요소를 모두 제거해서 요소들이 일관되도록 만드는 거예요. 이 경우라면 보통 리스트를 제거하고, 이제 쓰지 않는 매개변수를 어떻게 처리할지 결정하면 돼요.

union(Map<String, String> a, List<String> b, Map<String, String> c) => {
  ...a,
  ...c,
};

두 번째 해결 방법은 어느 한 종류의 요소를 다른 요소들과 일관되게 바꾸는 거예요. 예를 들어 리스트의 요소들을 자기 자신을 가리키는 키(key)로 추가할 수 있어요.

union(Map<String, String> a, List<String> b, Map<String, String> c) => {
  ...a,
  for (String s in b) s: s,
  ...c,
};

더 알아보기