🐙

【Dart3】type_literal_in_constant_patternのすすめ

2023/08/12に公開

はじめに

皆さんDart3には慣れましたか?僕はあまり使いこなせていないです😇
今回はDart3使う時type_literal_in_constant_patternってLintルールを有効にしないと罠だな〜と思ったので共有します。

本編

自分が罠と感じた部分について触れていきます。

変数のTypeでパターンマッチするシンプルな書き方

Object?型の変数xのTypeでパターンマッチするとき、シンプルな書き方としては以下のようなものがあります。

if文の場合(Variable patterns + Wildcard patterns)
void f(Object? x) {
  if (x case num _) {
    print('int or double');
  }
}
if文の場合(Object patterns)
void f2(Object? x) {
  if (x case num()) {
    print('int or double');
  }
}
switch文の場合(Variable patterns + Wildcard patterns)
void f3(Object? x) {
  switch (x) {
    case num _:
      print('int or double');
  }
}
switch文の場合(Object patterns)
void f4(Object? x) {
  switch (x) {
    case num():
      print('int or double');
  }
}

Variable patterns、Wildcard patternsなどについては以下参照

https://dart.dev/language/pattern-types

更にシンプルにしたい

どうせコードを書くならシンプルにしたいですよね。そこで先程のケースを以下のようにしてみたくなる人もいると思います。

if文の場合(???)
void f5(Object? x) {
  if (x case num) {
    print('int or double');
  }
}
switch文の場合(???)
void f6(Object? x) {
  switch (x) {
    case num:
      print('int or double');
  }
}

f5とf6の書き方は一見さらにシンプルになって良さそうに見えますが、f1〜f4のころとは意味が変わってしまいます。実際に実行するとprintを通らない様になっているかと思います。

何が違うのか

f1〜f4は変数xのTypeがnumかをパターンマッチしているのに対し、f5,f6は変数xがnumかをパターンマッチしています。
以下の様な感じです。

void main() {
  const x = 1;
  const x2 = num;
  // printされる
  f(x);
  // printされない
  f(x2);

  // printされない
  f5(x);
  // printされる
  f5(x2);
}

対策方法

Dart3から追加されたtype_literal_in_constant_patternというルールを有効にするとf5, f6の書き方をした際に警告がでるようになります。
更にquick fixでVariable patterns + Wildcard patternsに修正されるようになります。

このtype_literal_in_constant_patternですが、flutter createしたときにデフォルトで設定されるflutter_lintsのルールには含まれていません。

具体的な対策方法1:ルールを追加する

analysis_options.yamlにtype_literal_in_constant_patternを追加することで対策できます

analysis_options.yaml
linter:
  rules:
    - type_literal_in_constant_pattern

具体的な対策方法2:他のパッケージを使う

Flutter推奨のflutter_lints以外のパッケージを使うことも考えられます。例えばpedantic_monoだとtype_literal_in_constant_patternがはじめから有効です。

変数xがnum Typeかをパターンマッチしたい場合は?

type_literal_in_constant_patternを有効にすると変数xがnumかパターンマッチしたくてf5, f6の書き方をしてもquick fixで修正されてしまいます。
その場合は以下のように書きます。こうすれば警告がでません。

void f7(Object? x) {
  if (x case const (num)) {
    print('int or double');
  }
}

void f8(Object? x) {
  switch (x) {
    case const (num):
      print('int or double');
  }
}

まとめ

type_literal_in_constant_patternのすすめでした👍

GitHubで編集を提案
株式会社ゆめみ

Discussion