avoid_futureor_void 규칙: 결과 타입으로 FutureOr 사용 피하기
avoid_futureor_void 규칙: 결과 타입으로 FutureOr 사용 피하기
avoid_futureor_void는 결과(result)의 타입으로 FutureOr<void>를 쓰지 말라고 알려주는 린트(lint) 규칙이에요. FutureOr<void>는 결과가 Future<void>이거나 버려져야 한다는 뜻처럼 보이지만, 실제로는 둘 중 어느 쪽인지 안전하게 판별할 방법이 없어 문제가 돼요.
본문
설명
결과의 타입으로 FutureOr<void>를 쓰지 마세요. 이 타입은 결과가 Future<void>이거나, 결과가 버려져야 한다는 뜻(void일 때)을 담는 것처럼 보일 수 있어서 문제가 돼요. 하지만 실제로 우리가 이 두 경우 중 어느 쪽인지 안전하게 판별할 방법은 없어요(void 타입의 표현식은 어떤 객체든 평가될 수 있고, 어떤 타입의 future도 될 수 있기 때문이에요).
또한 "이 객체는 무시하고, 다만 future일 수 있으니 한번 봐줘" 같은 의미를 가진 타입은 개념적으로도 건전하지 않아요.
FutureOr<void> 타입의 반변(contravariant) 위치에서의 사용(예: 형식 매개변수의 타입)은 예외로, 이 경우에는 경고를 내보내지 않아요. 그 이유는 이 타입이 결과를 설명하는 게 아니라 다른 쪽이 제공하는 값에 대한 제약을 설명하기 때문이에요. 마찬가지로 타입 별칭(type alias) 선언도 예외인데, 별칭은 반변 위치(예: 형식 매개변수의 타입)에서 사용될 수 있기 때문이에요. 그래서 타입 별칭 선언에서는 타입 매개변수의 경계(bound)만 검사해요.
FutureOr<void>를 대체할 때 자주 유용한 타입으로는 Future<void>?가 있어요. 이 타입은 결과가 Future<void>이거나 null임을 담아내고, 어떤 객체도 두 타입을 동시에 가질 수 없기 때문에 실행 시점에 모호함이 없어요.
Future<void>?를 FutureOr<void>의 대체 타입으로 항상 쓸 수 있는 건 아니에요. 후자는 모든 타입의 슈퍼타입이지만 전자는 그렇지 않기 때문이에요. 이런 경우에는 FutureOr<void>를 void 타입으로 바꾸는 게 유용한 해결책이 될 수 있어요.
BAD:
FutureOr<void> m() {...}
GOOD:
Future<void>? m() {...}
이 규칙은 실험적(Experimental)이에요. 평가 중인 규칙이라 변경되거나 제거될 수 있어요. 이 규칙의 동작에 대한 피드백은 환영해요! 관련된 주요 이슈는 dart-lang/sdk#59292예요.
활성화
avoid_futureor_void 규칙을 활성화하려면 analysis_options.yaml 파일의 linter > rules에 avoid_futureor_void를 추가해요.
linter:
rules:
- avoid_futureor_void
YAML map 문법으로 린터 규칙을 설정한다면 linter > rules에 avoid_futureor_void: true를 추가해요.
linter:
rules:
avoid_futureor_void: true