Ce face typedef
typedef creează un alias: un nume nou pentru un tip existent. Cel mai des se folosește pentru tipuri de funcții, care altfel se scriu lung: typedef Validator = String? Function(String valoare);. După aceea scrii Validator peste tot.
Din Dart 2.13, aliasul poate fi pentru orice tip, nu doar pentru funcții: typedef Catalog = Map<String, List<int>>;. Aliasul poate avea și parametri generici.
Aliasul nu creează un tip nou: Catalog și Map<String, List<int>> sunt exact același tip. Dacă vrei un tip separat, care nu se amestecă cu cel original, folosește extension type sau o clasă.
Exemple
Exemplul 1: Alias pentru un tip de funcție
Validator este o funcție care întoarce un mesaj de eroare sau null.
typedef Validator = String? Function(String valoare);
String? nuEGol(String v) => v.trim().isEmpty ? 'câmpul este obligatoriu' : null;
String? esteEmail(String v) => v.contains('@') ? null : 'email invalid';
void valideaza(String valoare, List<Validator> reguli) {
for (final regula in reguli) {
final eroare = regula(valoare);
if (eroare != null) {
print('"$valoare": $eroare');
return;
}
}
print('"$valoare": valid');
}
void main() {
final reguli = [nuEGol, esteEmail];
valideaza('', reguli);
valideaza('ana.exemplu.ro', reguli);
valideaza('ana@exemplu.ro', reguli);
}
Rezultat
"": câmpul este obligatoriu
"ana.exemplu.ro": email invalid
"ana@exemplu.ro": valid
Exemplul 2: Alias pentru un tip lung
Catalog este doar alt nume pentru map-ul cu liste de note: compararea celor două tipuri dă true.
typedef Catalog = Map<String, List<int>>;
double mediaElevului(Catalog c, String elev) {
final note = c[elev] ?? [];
return note.isEmpty ? 0 : note.reduce((a, b) => a + b) / note.length;
}
void main() {
final Catalog clasa = {'Ana': [10, 9], 'Paul': [7, 8, 6]};
print(Catalog == Map<String, List<int>>);
print('Ana: ${mediaElevului(clasa, 'Ana')}, Paul: ${mediaElevului(clasa, 'Paul')}');
}
Rezultat
true
Ana: 9.5, Paul: 7.0
Exemplul 3: typedef generic
Transformare<T> se poate folosi cu orice tip.
typedef Transformare<T> = T Function(T);
List<T> aplicaDeDouaOri<T>(List<T> valori, Transformare<T> f) =>
valori.map((v) => f(f(v))).toList();
void main() {
print(aplicaDeDouaOri<int>([1, 2, 3], (x) => x * 10));
print(aplicaDeDouaOri<String>(['da'], (s) => '$s!'));
}
Rezultat
[100, 200, 300]
[da!!]
Greșeli frecvente
- Să crezi că
typedefcreează un tip nou, separat:typedef Lei = double;acceptă oricedouble. Pentru siguranță foloseșteextension type. - Sintaxa veche
typedef int Operatie(int a, int b);încă merge, dar forma cu=șiFunctioneste cea recomandată. - Alias-uri pentru tipuri scurte și clare:
typedef Text = String;doar încurcă cititorul.
Comenzi înrudite
funcții: Blocuri de cod cu nume, care primesc parametri și returnează o valoare; în Dart sunt și obiecte.generics: Clase și funcții cu tipuri ca parametri (<T>), care funcționează la fel pentru orice tip, păstrând verificarea tipurilor.extension type: Un tip nou, verificat la compilare, care la rulare este doar o valoare existentă (de ex. un int), fără cost.