관리 메뉴

나만을 위한 블로그

[Flutter] typedef란? 본문

Flutter

[Flutter] typedef란?

참깨빵위에참깨빵_ 2025. 10. 18. 03:45
728x90
반응형

https://dart.dev/language/typedefs

 

Typedefs

Learn about type aliases in Dart.

dart.dev

타입 별칭(type alias)은 typedef 키워드로 선언되고 타입을 간결하게 참조하는 방법이다. IntList라는 타입 별칭을 선언하고 쓰는 예는 아래와 같다

 

typedef IntList = List<int>;
IntList il = [1, 2, 3];

 

타입 별칭은 타입 파라미터를 가질 수 있다

 

typedef ListMapper<X> = Map<X, List<X>>;
Map<String, List<String>> m1 = {}; // 장황함
ListMapper<String> m2 = {}; // 같은 내용을 더 짧고 명확하게

 

2.13 이전엔 typedef가 함수 타입으로만 제한됐다. 새 타입 정의를 사용하려면 최소 2.13 이상의 버전을 써야 한다
대부분의 경우 함수에 대해 typedef 대신 inline 함수 타입을 쓰는 걸 권장한다. 그러나 함수 typedef는 여전히 유용할 수 있다

 

typedef Compare<T> = int Function(T a, T b);

int sort(int a, int b) => a - b;

void main() {
  assert(sort is Compare<int>); // True!
}

 

typedef는 함수 시그니처를 정의한 타입 별칭을 선언하는 키워드다. 함수 뿐 아니라 자료형에도 사용할 수 있다.

사용법은 아래와 같다.

 

typedef myInt = int;

myInt calc() {
  // int를 리턴하는 로직
}

void main() {
  myInt value = 100;
  print(value is int); // true
}

 

int를 myInf로 쓰겠다고 선언한 후 calc 함수, 메인 함수에서 myInt를 int 대신 사용하는 게 보인다. int가 맞는지 타입 체크 결과를 출력해도 true가 출력된다.

하지만 int, double 같은 기본형에 써봤자 별 의미가 없다. 그나마 리스트 같은 컬렉션에 쓰는 게 더 나아 보인다.

 

typedef StringList = List<String>;

StringList reverseName(StringList nameList) {
  var list = nameList.reversed;
  return list.toList(); // Iterable을 리턴하기 때문에 리스트를 리턴시키려면 toList() 사용 필요
}

void main() {
  var list = ["a", "b", "c"];
  print(reverseName(list)); // [c, b, a]
}

 

하지만 이 예시도 굳이 typedef를 써야 하나 싶다. typedef는 함수 타입에 적용했을 때 가독성이 꽤 나아진다.

 

https://stackoverflow.com/a/70327189

 

In which case do we need to use typedef in dart | flutter?

when I used the typedef in the code it didn't do anything extra except increase my line of code. I need to know when to use typedef and when to avoid it? Code snippet using typedef typedef SaySomet...

stackoverflow.com

내 생각에 typedef가 필요한 경우는 거의 없지만 긴 코드 반복을 피할 때 도움 될 수 있다. 아래 예시 클래스를 보라

 

class MyClass {
  MyClass(this.value, {
    this.onChange,
    this.onSubmit,
    this.onCancel,
    this.onDelete,
    this.onReset,
  });

  Map<String, Map<int, List<double>>> value;
  
  void Function(Map<String, Map<int, List<double>>>)? onChange;
  void Function(Map<String, Map<int, List<double>>>)? onSubmit;
  void Function(Map<String, Map<int, List<double>>>)? onCancel;
  void Function(Map<String, Map<int, List<double>>>)? onDelete;
  void Function(Map<String, Map<int, List<double>>>)? onReset;
}

 

위 코드는 보기 흉하다. typedef를 쓰는 방법은 분명하다고 생각하지만 그래도 보여주겠다

 

typedef MyCallback = void Function(Map<String, Map<int, List<double>>>);

class MyClass {
  MyClass(this.value, {
    this.onChange,
    this.onSubmit,
    this.onCancel,
    this.onDelete,
    this.onReset,
  });

  Map<String, Map<int, List<double>>> value;

  MyCallback? onChange;
  MyCallback? onSubmit;
  MyCallback? onCancel;
  MyCallback? onDelete;
  MyCallback? onReset;
}
typedef MyClassValue = Map<String, Map<int, List<double>>>;

class MyClass {
  MyClass(this.value, {
    this.onChange,
    this.onSubmit,
    this.onCancel,
    this.onDelete,
    this.onReset,
  });

  MyClassValue value;

  void Function(MyClassValue)? onChange;
  void Function(MyClassValue)? onSubmit;
  void Function(MyClassValue)? onCancel;
  void Function(MyClassValue)? onDelete;
  void Function(MyClassValue)? onReset;
}

 

코드 자체가 더 깔끔해 보인다. 일반적으로 typedef는 함수를 매개변수로 넘기거나 함수에서 함수를 리턴하는 함수형 프로그래밍 패턴에 적합하다

 

이런 특징 때문에 typedef는 콜백을 만들거나 여러 제네릭 타입 매개변수를 매번 적어주기 귀찮을 때 유용하다.

참고로 다트 공식문에서 말하는 inline 함수는 아래 문서를 참고한다.

 

https://dart.dev/effective-dart/design#prefer-inline-function-types-over-typedefs

 

Effective Dart: Design

Design consistent, usable libraries.

dart.dev

 

위 문서에서도 함수 타입이 특히 길거나 자주 쓰이는 경우엔 여전히 typedef를 정의하는 게 유용할 수 있다고 하니 필요할 때 적절하게 쓰면 좋을 것이다.

반응형
Comments