avoid_generics_shadowing
v0.4.0 Warning Fix Code Organization
Flags a generic type parameter whose name is also a top-level declaration in the same file — a class, mixin, enum, typedef or extension type.
Inside that scope the name no longer means the class. Every annotation reading User looks like the model and is in fact an unbounded type parameter, so the compiler accepts a String where the author was certain only a User could arrive.
A quick fix renames the parameter to a free single letter.
This rule is in the recommended preset, so it is on with preset: recommended, preset: opinionated or preset: pedantic.
See also: Dart language - Generics | Dart lint: avoid_shadowing_type_parameters
class User { const User(this.id);
final String id;}
// `User` here is a type parameter, not the class above. `findById` accepts// and returns anything at all, and nothing in the signature says so.class Repository<User> { User findById(String id) => throw UnimplementedError();}class User { const User(this.id);
final String id;}
class Repository<T> { T findById(String id) => throw UnimplementedError();}Examples
Section titled “Examples”A method’s own type parameter shadows too
Section titled “A method’s own type parameter shadows too”The rule looks at every type parameter list in the file, not just a class’s:
enum Role { admin, guest }
class Permissions { // `Role` names the parameter, so `value` is unconstrained — `check(42)` // compiles. void check<Role>(Role value) {}}enum Role { admin, guest }
class Permissions { void check<T>(T value) {}}Descriptive names are fine as long as they do not collide
Section titled “Descriptive names are fine as long as they do not collide”Renaming to a single letter is what the quick fix offers, but any free name works:
class Order {}
class Invoice {}
// Reported — both parameters shadow a class in this fileclass Pair<Order, Invoice> { Pair(this.first, this.second);
final Order first; final Invoice second;}class Order {}
class Invoice {}
// Accepted — neither name is declared at the top level hereclass Pair<TFirst, TSecond> { Pair(this.first, this.second);
final TFirst first; final TSecond second;}Known limitations
Section titled “Known limitations”Only declarations in the same file count. A type parameter named after a class imported from another library is not reported — the rule reads the compilation unit’s own top-level declarations, so it cannot see what an import brought in.
Shadowing an outer type parameter is the SDK’s job. avoid_shadowing_type_parameters covers a method’s T hiding its class’s T; this rule covers a T hiding a real type.
The quick fix picks the first free letter. It skips names already used by sibling parameters, by types named in the declaring scope, and by top-level declarations, so the rename cannot reintroduce the collision — but the letter it lands on may not be the one you would have chosen.
Configuration
Section titled “Configuration”To turn it off:
rules: avoid_generics_shadowing: falseTo keep the rule on but skip certain paths, use per-rule exclude.
Related rules
Section titled “Related rules”arguments_ordering— Keep named arguments in a configured order.avoid_duplicate_mixins— Flag a mixin applied twice in onewithclause.avoid_unnecessary_constructor— Remove a constructor identical to the default one.avoid_unnecessary_extends— Remove an explicitextends Object.