type-annotate-public-apis

Same as type_annotate_public_apis in Dart lints

Group
Style
Path
lint/style/type-annotate-public-apis
Default
On (recommended)
Origin
Dart lints
Rule
443 of 512
recommended

Requires type annotations on public declarations.

A public API's types are part of its contract; leaving them to inference (or dynamic) makes the contract implicit and easy to break. Public top-level functions and methods need a return type (setters and operator []= excepted), their parameters need types, and public fields and top-level variables need a declared type unless they are const, or final with an initializer whose inferred type is neither dynamic nor Null. Parameters of public constructors of public, non-enum classes are checked too. Missing operator return types highlight the operator name alone.

var answer = 42;           // flagged
install(id, url) {}        // flagged
final pi = 3.14;           // ok: inferred `double`
void install(String id) {} // ok

The analyzer's visitor also descends into the initializers of untyped fields and top-level variables, flagging closure parameters and locals declared there; falcon checks only the declarations themselves, since those nested names are not public API.

Invalid

example.dartdart
// @dart = 3.13

var answer = 42;
final nothing = null;
late final pending;

install(String id) {}

void register(id, String url) {}

typedef Handler(event);

class Widget {
  var count = 0;
  static var shared;
  Widget(key);
  build() => null;
  void update(value) {}
  get label => '';
  set label(v) {}
  operator +(Widget other) => this;
}

// Primary constructors retain their written parameters, including modifiers.
class PrimaryFinal(final x);
class PrimaryVar(var x);
class PrimaryNamed.named(x);
class PrimaryPlain(x);
class PrimaryOptional({p});
class PrimaryTypeName(final Widget);
class PrimaryTypeNamePlain(Widget);
extension type Representation(i) {}

typedef void LegacyTypeName(int);
Missing type annotation on a public API.
2
3var answer = 42;
Missing type annotation on a public API.
3var answer = 42;
4final nothing = null;
Missing type annotation on a public API.
4final nothing = null;
5late final pending;
Missing type annotation on a public API.
6
7install(String id) {}
Missing type annotation on a public API.
8
9void register(id, String url) {}
Missing type annotation on a public API.
10
11typedef Handler(event);
Missing type annotation on a public API.
13class Widget {
14 var count = 0;
Missing type annotation on a public API.
14 var count = 0;
15 static var shared;
Missing type annotation on a public API.
15 static var shared;
16 Widget(key);
Missing type annotation on a public API.
16 Widget(key);
17 build() => null;
Missing type annotation on a public API.
17 build() => null;
18 void update(value) {}
Missing type annotation on a public API.
18 void update(value) {}
19 get label => '';
Missing type annotation on a public API.
19 get label => '';
20 set label(v) {}
Missing type annotation on a public API.
20 set label(v) {}
21 operator +(Widget other) => this;
Missing type annotation on a public API.
24// Primary constructors retain their written parameters, including modifiers.
25class PrimaryFinal(final x);
Missing type annotation on a public API.
25class PrimaryFinal(final x);
26class PrimaryVar(var x);
Missing type annotation on a public API.
26class PrimaryVar(var x);
27class PrimaryNamed.named(x);
Missing type annotation on a public API.
27class PrimaryNamed.named(x);
28class PrimaryPlain(x);
Missing type annotation on a public API.
28class PrimaryPlain(x);
29class PrimaryOptional({p});
Missing type annotation on a public API.
29class PrimaryOptional({p});
30class PrimaryTypeName(final Widget);
Missing type annotation on a public API.
30class PrimaryTypeName(final Widget);
31class PrimaryTypeNamePlain(Widget);
Missing type annotation on a public API.
31class PrimaryTypeNamePlain(Widget);
32extension type Representation(i) {}
Missing type annotation on a public API.
33
34typedef void LegacyTypeName(int);

Valid

example.dartdart
// @dart = 3.13

const version = '1.0';
final pi = 3.14;
final name = 'falcon';
var _private = 1;
int count = 0;

void install(String id) {}

_helper(x) {}

typedef void Handler(Object event);

class Widget {
  final int size;
  static const limit = 4;
  final title = 'widget';
  var _cache;
  Widget(this.size, {String? key});
  Widget._internal(x) : size = 0;
  _render(x) {}
  void update(int value, [_]) {}
  int get label => size;
  set label(int v) {}
  Widget operator +(Widget other) => this;
  operator []=(int i, int v) {}
}

class _Hidden {
  _Hidden(x);
}

enum Kind {
  a(1);
  final int v;
  const Kind(this.v);
}

void main() {
  local(x) {}
  local(1);
  print([_private, _Hidden(1), _helper]);
}

// Function-typed formals are not regular formals; the public-API helper stops
// at that boundary even when their nested parameter types are omitted.
void nestedTypeName(void g(int)) {}
void nestedUntyped(void cb(x)) {}
typedef void NestedCallback(void cb(x));
typedef ModernCallback = void Function(dynamic x);

class TypedPrimary(var int x);
class FinalPrimary(final String value);
class _PrivatePrimary(x);
class PrivateNamedPrimary._hidden(x);
class WildcardPrimary(_, __);
extension type TypedRepresentation(int value) {}

// Enum constructors are not public APIs, including declaring parameters.
enum PlainPrimaryEnum(p) {
  one(0)
}
enum DeclaringPrimaryEnum(final p) {
  one(0)
}

Configure type-annotate-public-apis

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "style": {
        "type-annotate-public-apis": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/style/type-annotate-public-apis: <reason>
  • type-init-formalstype_init_formalsrecommended

    Flags a *redundant* type annotation on an initializing formal or super parameter (type-init-formals, adopted from package:lints).

  • unawaited-futuresunawaited_futuresrecommended

    Future results in async bodies must be awaited or marked unawaited.

  • unintended-html-in-doc-commentunintended_html_in_doc_commentrecommended

    Flags angle-bracket text in doc comments that Markdown would render as an HTML tag.

  • unnecessary-await-in-returnunnecessary_await_in_return

    Avoid await on a returned Future the function's own Future already covers.

  • unnecessary-brace-in-string-interpsunnecessary_brace_in_string_interpsrecommended

    Flags ${x} string interpolations whose braces can be dropped.

  • unnecessary-breaksunnecessary_breaksrecommended

    Flags a trailing break in a switch case that already ends implicitly.

  • unnecessary-constructor-nameunnecessary_constructor_namerecommended

    Flags a redundant .new on constructor declarations and invocations.

  • unnecessary-finalunnecessary_final

    Don't use final for local variables and parameters.