WebエンジニアのためのDart入門 〜JS・TSとの比較で理解〜
はじめに
スマホアプリを開発できるフレームワークの「Flutter」で使われるDartを、特徴が類似しているJavaScriptやTypeScriptと比較して学習します。
Dartとは
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に相当します。
console.log('Hello world!');
print('Hello world!');
変数宣言
JavaScriptで再代入が不可能な変数はconst
を用いますが、Dartではfinal
を使用します。const
は別の意味を持つので注意してください。
変数名の前には型を記述できます。文字列であればString
となります。ただし、右辺の値から型推論できる場合には省略してシンプルに記述可能です。
const name = 'JavaScript';
final String name = 'dart'; // String型と明示的に指定
final otherName = 'Dart'; // String型と推論
null判定
JavaScriptではnull、0、空文字などは、論理値として扱う場合falseとみなされます。そのため、こうした値をまとめて!
演算子でチェックできます。
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などをそれぞれ等価演算子==
で比較することによってチェックします。
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では、アロー関数を使う場合は以下のようになります。
const fn = () => {
return true;
}
Dartではよりシンプルに記述できます。2つ目の書き方はアロー関数に似ていますが、{}
で括った書き方はできないので1行で完結するシンプルなワンライナー関数のための書式です。
fn() {
return true;
}
final fn = () => true;
非同期処理
ここではクラスの非同期メソッドを取り上げます。
JavaScriptではasync/awaitにより非同期処理を記述できます。
_getIPAddress
というメソッドは、IPアドレスを取得できる外部APIを呼び出すメソッドです。async
キーワードで非同期メソッドを宣言し、await
キーワードで非同期処理の結果を持ちます。
// 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
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を使う他にthen
やcatchError
で受け取ることができます。これはJavaScriptのPromiseとよく似ています。
また、http
パッケージを利用するためにインポートが必要です。これもJavaScriptと仕組みは似ていますが、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を使ったアプリ開発にもぜひ挑戦してみましょう。