WebエンジニアのためのDart入門 〜JS・TSとの比較で理解〜

公開日:2022-10-04
Dart

https://www.youtube.com/watch?v=HE_QTQi3JaI

はじめに

スマホアプリを開発できるフレームワークの「Flutter」で使われるDartを、特徴が類似しているJavaScriptやTypeScriptと比較して学習します。

Dartとは

https://dart.dev/https://dart.dev/

DartはGoogleによって開発されたプログラミング言語です。DartはJavaScriptに影響を受けた言語で、共通した特徴も持ち合わせています。

元々はJavaScriptの代替を目指して開発されましたが、スマホアプリ開発で用いられるFlutterというフレームワークに採用されたことで注目されている言語です。サーバサイドアプリやデスクトップアプリの開発に用いることもできます。

Dartの環境構築

Dartのインストール

公式ページに記載のように、macOSのhomebrewやWindowsのchocoといったパッケージマネージャを用いることでインストールできます。

コマンドラインツールからプロジェクトを作成

今回の記事ではFlutterなどのフレームワークは使わず、Dartの言語を学習することにフォーカスします。
こちらも公式のCLIの説明に沿って進めます。

まずは、dart createコマンドでDartプロジェクトを作成します。-tオプションで雛形を指定できるので、consoleを渡してコマンドラインアプリケーションの雛形を利用します。

ここではプロジェクト名をdart_sampleとしています。

dart create -t console dart_sample

dart_sampleというディレクトリにさまざまなファイルが作成されます。

静的解析とテスト

作成したディレクトリへ移動すると、dart analyzeによる静的解析やdart testによるテストコマンドが利用できます。

静的解析のルールは、analysis_options.yamlに記載されています。テンプレートから作成した時点では、公式で推奨されているルール設定が書かれたrecommended.yamlというファイルを読み込んでいます。また、テストコードはtestディレクトリ配下にあります。

cd dart_sample
dart analyze
dart test

実行

プログラムの実行は、dart runコマンドを用います。テンプレート作成時点ではbin/dart_sample.dartがエントリーポイントになっているのでこのファイルを指定します。

bin/dart_sample.dartは、lib/dart_sample.dart内のcalculate関数を呼び出し、42という結果を表示するといった内容です。

$ dart run bin/dart_sample.dart
Hello world: 42!

パッケージマネージャー

Dartには標準でdart pubというパッケージマネージャーが備わっています。これはNode.jsにおけるnpmやyarnに相当し、dart pubを用いることで外部パッケージを追加できます。

使用するパッケージやバージョンはpubspec.yamlというファイルで管理されます。Node.jsにおけるpackage.jsonに相当します。

パッケージの追加

パッケージの追加にはdart pub addコマンドを利用します。例えば、httpクライアントのパッケージhttpを追加する場合には以下のようになります。

dart pub add http

パッケージの追加が完了すると、pubspec.yaml内に dependencies: {http: ^0.13.4} というような記述が追加されます。Node.jsのパッケージマネージャーと使い勝手が近いとわかります。

JavaScript, TypeScriptとDartの比較

DartはJavaScriptやTypeScriptと類似した点もあるため、今回は比較をしながらDartの基礎を紹介します。公式ガイドにも比較ページが用意されています。

言語仕様としてはJavaScriptに近い一方で、JavaScriptの曖昧さを排除するように作られていることからJavaやC#に近い厳格さも持ち合わせています。このDartの特徴は、JavaScriptに型情報を付与するTypeScriptとよく似ています。

また、未定義値undefinedが無い点や、厳密な等価===がなく==で型のチェックができます。

デバッグ

Dartではコンソールへの出力にprint関数を使用します。JavaScriptのconsole.logに相当します。

JavaScript(参考)
console.log('Hello world!');
Dart
print('Hello world!');

変数宣言

JavaScriptで再代入が不可能な変数はconstを用いますが、Dartではfinalを使用します。constは別の意味を持つので注意してください。

変数名の前には型を記述できます。文字列であればStringとなります。ただし、右辺の値から型推論できる場合には省略してシンプルに記述可能です。

JavaScript(参考)
const name = 'JavaScript';
Dart
final String name = 'dart'; // String型と明示的に指定
final otherName = 'Dart'; // String型と推論

null判定

JavaScriptではnull、0、空文字などは、論理値として扱う場合falseとみなされます。そのため、こうした値をまとめて!演算子でチェックできます。

JavaScript(参考)
const myNull = null;
if (!myNull) {
  console.log('null is treated as false');
}
const zero = 0;
if (!zero) {
  console.log('0 is treated as false');
}

Dartでは、JavaScriptのように様々な値を論理値に変換することはせず、nullや0などをそれぞれ等価演算子==で比較することによってチェックします。

Dart
final myNull = null;
if (myNull == null) {
  print('use "== null" to check null');
}
final zero = 0;
if (zero == 0) {
  print('use "== 0" to check zero');
}

関数

JavaScriptでは、アロー関数を使う場合は以下のようになります。

JavaScript(参考)
const fn = () => {
  return true;
}

Dartではよりシンプルに記述できます。2つ目の書き方はアロー関数に似ていますが、{}で括った書き方はできないので1行で完結するシンプルなワンライナー関数のための書式です。

Dart
fn() {
  return true;
}
final fn = () => true;

非同期処理

ここではクラスの非同期メソッドを取り上げます。

JavaScriptではasync/awaitにより非同期処理を記述できます。
_getIPAddressというメソッドは、IPアドレスを取得できる外部APIを呼び出すメソッドです。asyncキーワードで非同期メソッドを宣言し、awaitキーワードで非同期処理の結果を持ちます。

JavaScript(参考)
// JavaScript
class Example {
  async _getIPAddress() {
    const url = 'https://httpbin.org/ip';
    const res = await fetch(url);
    const json = await res.json();
    return json.origin;
  }
}

Dartの場合も構文はよく似ていますが、asyncの位置が()の後ろにくるといった違いがあります。

Dart
// Dart
import 'dart:convert';
import 'package:http/http.dart' as http;

class Example {
  _getIPAddress() async {
    final url = 'https://httpbin.org/ip';
    final uri = Uri.parse(url);
    final res = await http.get(uri);
    return jsonDecode(res.body)['origin'];
  }
}

非同期処理の例を実行する

最後に紹介した非同期処理の例を、実際に動かしてみましょう。

先ほどはクラスを定義しただけなので、main関数内でExample()とインスタンス化してexampleに代入します。このインスタンスから_getIPAddressメソッドを呼び出します。

非同期処理の結果やエラーは、async/awaitを使う他にthencatchErrorで受け取ることができます。これはJavaScriptのPromiseとよく似ています。

また、httpパッケージを利用するためにインポートが必要です。これもJavaScriptと仕組みは似ていますが、Dartのインポートはパッケージ名が先にきます。

dart_sample.dart
import 'dart:convert';

import 'package:http/http.dart' as http;

class Example {
  _getIPAddress() async {
    final url = 'https://httpbin.org/ip';
    final uri = Uri.parse(url);
    final res = await http.get(uri);
    return jsonDecode(res.body)['origin'];
  }
}

void main() {
  final example = Example();
  example
      ._getIPAddress()
      .then((ip) => print(ip))
      .catchError((error) => print(error));
}

まとめ

今回はDartの基本機能を紹介しました。JavaScriptに慣れた開発者にとっては、類似した文法も多く取り組みやすくなっています。Dartの基礎を学んだ後はFlutterを使ったアプリ開発にもぜひ挑戦してみましょう。