ambiguous_set_or_map_literal_either 진단: set인지 map인지 결정할 정보가 없을 때

ambiguous_set_or_map_literal_either 진단: set인지 map인지 결정할 정보가 없을 때

Dart 분석기가 내보내는 진단에는 이름이 있어요. ambiguous_set_or_map_literal_either리터럴이 map이거나 set이어야 하는데, 요소들에 타입 추론이 작동할 만한 정보가 충분하지 않을 때 분석기가 알려주는 컴파일 타임 진단이에요.

출처: ambiguous_set_or_map_literal_either

본문

설명

map 리터럴과 set 리터럴은 같은 구분 기호({})를 쓰기 때문에, 분석기는 타입 인자와 요소들을 보고 어느 쪽 리터럴인지 판단해요. 타입 인자가 없고 모든 요소가 전개 요소(두 종류 리터럴 모두에서 허용됨)라면, 분석기는 전개되는 표현식들의 타입을 사용해요. 모든 표현식이 Iterable 타입이면 set 리터럴이고, 모두 Map 타입이면 map 리터럴이에요.

이 진단은 전개되는 표현식 중 어느 것도 map 리터럴을 쓰는 건지 set 리터럴을 쓰는 건지 결정할 만한 타입을 갖지 않을 때 만들어져요.

예시

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

union(a, b) => {...a, ...b};

이 문제가 생기는 이유는 타입 인자가 없고, ab 어느 쪽의 타입에 대한 정보도 없기 때문이에요.

흔한 해결 방법

이 문제를 고치는 흔한 방법은 세 가지예요. 첫 번째는 리터럴에 타입 인자를 추가하는 거예요. 예를 들어 리터럴이 map 리터럴이 되길 의도했다면 다음과 같이 쓸 수 있어요.

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

두 번째 해결 방법은 표현식들이 Iterable 타입이나 Map 타입을 갖도록 타입 정보를 추가하는 거예요. 명시적 캐스트(cast)를 추가하거나, 이 경우라면 두 매개변수의 선언에 타입을 추가하면 돼요.

union(List<int> a, List<int> b) => {...a, ...b};

세 번째 해결 방법은 컨텍스트 정보를 추가하는 거예요. 이 경우에는 함수에 반환 타입을 추가하면 돼요.

Set<String> union(a, b) => {...a, ...b};

다른 경우에는 다른 곳에 타입을 추가할 수도 있어요. 예를 들어 원래 코드가 다음과 같다고 해볼게요.

union(a, b) {
  var x = {...a, ...b};
  return x;
}

x에 타입 애너테이션을 붙일 수 있어요.

union(a, b) {
  Map<String, String> x = {...a, ...b};
  return x;
}

더 알아보기