@@ -1426,18 +1426,21 @@ var completer = Completer<Map<String, int>>();
14261426
14271427
14281428<a id =" do-annotate-with-dynamic-instead-of-letting-inference-fail " aria-hidden =" true " ></a >
1429+
14291430### DO annotate with ` Object? ` instead of letting inference fail
14301431
1431- When inference doesn't fill in a type, it usually defaults to ` dynamic ` , which
1432- is rarely the best type to use. A ` dynamic ` reference allows for unsafe
1433- operations that use identical syntax to operations that are statically safe when
1434- the type is not ` dynamic ` . An ` Object? ` reference is safer. For example a
1435- ` dynamic ` reference may fail a type cast that is not visible in the syntax,
1436- while an ` Object? ` reference will guarantee that the ` as ` cast is written in
1437- source.
1432+ When inference doesn't fill in a type, it usually defaults to ` dynamic ` ,
1433+ which is rarely the best type to use.
1434+ A ` dynamic ` reference allows for unsafe operations that
1435+ use identical syntax to operations that are
1436+ statically safe when the type is not ` dynamic ` .
1437+ An ` Object? ` reference is safer.
1438+ For example, a ` dynamic ` reference might fail a type cast that
1439+ is not visible in the syntax, while an ` Object? ` reference will
1440+ guarantee that the ` as ` cast is explicitly written.
14381441
1439- Use ` Object? ` to indicate in a signature that any type of object, or null, is
1440- allowed.
1442+ Use ` Object? ` to indicate in a signature that
1443+ any type of object, or null, is allowed.
14411444
14421445<? code-excerpt "design_good.dart (prefer-object-question)"?>
14431446``` dart tag=good
@@ -1449,18 +1452,21 @@ Object? mergeJson(Object? original, Object? changes) => ...
14491452mergeJson(original, changes) => ...
14501453```
14511454
1452- In the cases where a dynamic member will be invoked this is technically the most
1453- terse way to get a dynamic reference. However, it's not the most * clear* way. A
1454- casual reader of your code who sees that an annotation is missing has no way of
1455- knowing if you intended it to be ` dynamic ` , expected inference to fill in some
1456- other type, or simply forgot to write the annotation. When ` dynamic ` is the type
1457- you want, write that explicitly to make your intent clear and highlight that
1458- this code has less static safety.
1455+ In the cases where a dynamic member will be invoked,
1456+ this is technically the tersest way to get a dynamic reference.
1457+ However, it's not the most * clear* way.
1458+ A casual reader of your code who sees that an annotation is missing has
1459+ no way of knowing if you intended it to be ` dynamic ` ,
1460+ expected inference to fill in some other type,
1461+ or simply forgot to write the annotation.
1462+ When ` dynamic ` is the type you want,
1463+ write that explicitly to make your intent clear and
1464+ highlight that this code has less static safety.
14591465
14601466::: note
1461- With Dart's strong type system and type inference,
1462- users expect Dart to behave like an inferred statically-typed language.
1463- With that mental model,
1467+ With Dart's strong type system and type inference,
1468+ users expect Dart to behave like an inferred statically-typed language.
1469+ With that mental model,
14641470it is an unpleasant surprise to discover that
14651471a region of code has silently lost all of the
14661472safety and performance of static types.
@@ -1658,6 +1664,7 @@ where you must use the new syntax.
16581664
16591665
16601666<a id =" avoid-using-dynamic-unless-you-want-to-disable-static-checking " aria-hidden =" true " ></a >
1667+
16611668### AVOID using ` dynamic ` unless you want to invoke dynamic members
16621669
16631670Some operations work with any possible object. For example, a ` log() ` method
@@ -1688,17 +1695,18 @@ bool convertToBool(Object arg) {
16881695}
16891696```
16901697
1691- Prefer using ` Object? ` over ` dynamic ` in code that is not invoking a member
1692- dynamically, even when working with existing APIs that use ` dynamic ` . For
1693- example, the static types ` Map<String, dynamic> ` and ` Map<String, Object?> ` can
1694- both be used as the static type for the same value, and the ` Object? ` form is
1695- preferred.
1698+ Prefer using ` Object? ` over ` dynamic ` in code not invoking a member dynamically,
1699+ even when working with existing APIs that use ` dynamic ` .
1700+ For example, the static types ` Map<String, dynamic> ` and ` Map<String, Object?> `
1701+ can both be used as the static type for the same value, and
1702+ the ` Object? ` form is preferred.
16961703
1697- For intentional dynamic member access, consider using a cast to ` dynamic ` for
1698- the member access specifically. Separating the use of ` Object? ` for non-dynamic
1699- behavior and limiting ` dynamic ` to the places where dynamic operations are
1704+ For intentional dynamic member access, consider
1705+ using a cast to ` dynamic ` for the member access specifically.
1706+ Separating the use of ` Object? ` for non-dynamic behavior and
1707+ limiting ` dynamic ` to the places where dynamic operations are
17001708intended makes them syntactically distinct and highlights the places where
1701- mistakes like misspellings may not be caught by static type checking .
1709+ static type checking might not catch mistakes like misspellings .
17021710
17031711<? code-excerpt "design_good.dart (cast-for-dynamic-member)"?>
17041712``` dart tag=good
0 commit comments