@@ -325,7 +325,8 @@ Of course, if `null` is a valid initialized value for the variable,
325
325
then it probably does make sense to have a separate boolean field.
326
326
327
327
328
- ### CONSIDER assigning a nullable field to a local variable to enable type promotion
328
+ ### CONSIDER work arounds to bypass type promotion limitations
329
+ (or, "...to enable type promotion")
329
330
330
331
Checking that a nullable variable is not equal to ` null ` promotes the variable
331
332
to a non-nullable type. That lets you access members on the variable and pass it
@@ -337,7 +338,31 @@ private final fields. Values that are open to manipulation
337
338
338
339
Declaring members [ private] [ ] and [ final] [ ] , as we generally recommend, is often
339
340
enough to bypass these limitations. But, that's not always an option.
340
- One pattern to work around this is to assign the field's value
341
+
342
+ One pattern to work around type promotion limitations is to use a
343
+ [ null-check pattern] [ ] to simultaneously confirm the member's value is not null,
344
+ and bind that value to a new non-nullable variable of the same base type.
345
+
346
+ <? code-excerpt "usage_good.dart (null-check-promo)"?>
347
+ ``` dart tag=good
348
+ class UploadException {
349
+ final Response? response;
350
+
351
+ UploadException([this.response]);
352
+
353
+ @override
354
+ String toString() {
355
+ if (this.response case var response?) {
356
+ return 'Could not complete upload to ${response.url} '
357
+ '(error code ${response.errorCode}): ${response.reason}.';
358
+ }
359
+
360
+ return 'Could not upload (no response).';
361
+ }
362
+ }
363
+ ```
364
+
365
+ Another work around is to assign the field's value
341
366
to a local variable. Null checks on that variable will promote,
342
367
so you can safely treat it as non-nullable.
343
368
@@ -361,8 +386,16 @@ class UploadException {
361
386
}
362
387
```
363
388
364
- Assigning to a local variable can be cleaner and safer than using ` ! ` every
365
- time you need to treat the value as non-null:
389
+ Be careful when using a local variable. If you need to write back to the field,
390
+ make sure that you don't write back to the local variable instead. (Making the
391
+ local variable [ ` final ` ] [ ] can prevent such mistakes.) Also, if the field might
392
+ change while the local is still in scope, then the local might have a stale
393
+ value.
394
+
395
+ Sometimes it's best to simply [ use ` ! ` ] [ ] on the field.
396
+ In some cases, though, using either a local variable or a null-check pattern
397
+ can be cleaner and safer than using ` ! ` every time you need to treat the value
398
+ as non-null:
366
399
367
400
<? code-excerpt "usage_bad.dart (shadow-nullable-field)" replace="/!\./[!!!]./g"?>
368
401
``` dart tag=bad
@@ -383,15 +416,10 @@ class UploadException {
383
416
}
384
417
```
385
418
386
- Be careful when using a local variable. If you need to write back to the field,
387
- make sure that you don't write back to the local variable instead. (Making the
388
- local variable [ ` final ` ] [ ] can prevent such mistakes.) Also, if the field might
389
- change while the local is still in scope, then the local might have a stale
390
- value. Sometimes it's best to simply [ use ` ! ` ] [ ] on the field.
391
-
392
419
[ can't be type promoted ] : /tools/non-promotion-reasons
393
420
[ private ] : /effective-dart/design#prefer-making-declarations-private
394
421
[ final ] : /effective-dart/design#prefer-making-fields-and-top-level-variables-final
422
+ [ null-check pattern ] : /language/pattern-types#null-check
395
423
[ `final` ] : /effective-dart/usage#do-follow-a-consistent-rule-for-var-and-final-on-local-variables
396
424
[ use `!` ] : /null-safety/understanding-null-safety#non-null-assertion-operator
397
425
0 commit comments