🙄

【Dart/TypeScript】共通点と違い。型推論ありの静的型付け・単一継承・抽象クラス・Mixin・非同期

2024/04/06に公開

はじめに

FlutterとReactの両方のフレームワークを別々のプロジェクトで使っているので、プログラミング言語(DartとTypeScript)とフレームワーク(FlutterとReact)の共通点と違いについて、備忘録としてまとめておく。この記事ではプログラミング言語に関して。

DartとTypeScriptの共通点と違い

Dart:https://dart.dev/language

TypeScript:https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html

型システム:型推論ありの静的型付け・型注釈オプショナル

Dart, TypeScriptともに静的型付け言語(コンパイル時に型が決定する)だが、型注釈はオプショナルで強力な型推論が働く。

Dart:var(変数キーワード)・const・final・late(変数修飾子)

https://dart.dev/language/variables

  • var:初期化後も再代入が可能。型は初期化時に右辺の式からコンパイラによって推論される
  • const:コンパイル時定数。varとは組み合わせ不可
  • final:コンパイル時ではなく実行時定数。varとは組み合わせ不可
  • late:実行時に設定される遅延初期化。変数が宣言された後で初期化が行われ、初期化が行われるまで変数は値を持たない。varと組み合わせれば初期化後の再代入が可能。
// 型推論
var number = 42; // `number`はintと推論される
number = 100;    // 再代入可能
final name = 'Alice'; // `name`はStringと推論される

// 変数修飾子
const int x = 10; // コンパイル時定数。その後再代入不可能
final int x = 10; // 実行時定数。その後再代入不可能
late int x;
void main() {
  x = 10; // 初期化が遅延されているため、実行時に初期化
  print(x); // 10
}
late var number = getNumber(); // 実行時に初期化されるが、再代入可能

int add(int a, int b) {
  return a + b;
}

TypeScript:let(変数キーワード)const・readonly(変数修飾子)

  • let:変数宣言。再代入可能。同じスコープ内での再宣言は不可能。
  • const:コンパイル時定数。再代入不可
  • readonly:実行時定数というよりは変更不可のプロパティ。主にクラスのプロパティやインターフェースのフィールドに対して使用される。Dartの**finalに近い概念だが、readonly**は変数宣言には使用されない。
  • dartのlateに直接相当する機能はない
// 型推論
let number = 42; // `number`は`number`型と推論される
number = 39; //再代入可能
const name = 'Alice'; // `name`は`string`型と推論される
name = 'Bob'; //エラー。再代入不可

// 変数修飾子
const PI = 3.14; // コンパイル時定数

class Example {
    readonly constantValue: number = 10; // クラスのプロパティとしてのreadonly
}
const example = new Example();
// example.constantValue = 15; // エラー: cannot assign to 'constantValue' because it is a read-only property.

// add関数のパラメータ`x`と`y`、戻り値は型推論により`any`型とされる
function add(x, y) {
  return x + y;
}

// add関数のパラメータに型注釈を追加(推奨)
function add(x: number, y: number) {
  return x + y; // 戻り値は`number`型と推論される
}

関数:引数(オプション・名前つき・必須)

Dart

  • 一般的な定義の他にオプション引数/名前つき引数/必須引数が設定できる
// オプション引数
// 引数がなくても呼び出せる(デフォルトの値が使われる)
void func1(String param1, [int param2=0]){
  print("$param1,$param2");
}
// 名前つき引数
// 名前を指定して呼び出せる
void func2({String? param1, int? param2}){
  print("$param1,$param2");
}
// 必須引数
// 必ず引数を渡すことを強制できる
void func3({required String param1, required int param2}){
  print("$param1,$param2");
}
void main() {
  func1("func1");
  func2(param1:"func2");
  func3(param1:"func3",param2:3);
}

// 出力結果
// func1,0
// func2,null
// func3,3

TypeScript

// オプション引数
// 引数がない場合、undefinedがデフォルト値として使われる
function func1(param1: string, param2?: number) {
  console.log(`${param1}, ${param2}`);
}

// 名前付き引数(オブジェクトを引数として使用)
// 引数の順番に関係なく、名前で指定して値を渡すことができる
function func2({param1, param2}: {param1?: string, param2?: number}) {
  console.log(`${param1}, ${param2}`);
}

// 必須引数
// 引数の前に`?`をつけないと、その引数は必須となる
function func3(param1: string, param2: number) {
  console.log(`${param1}, ${param2}`);
}

func1("func1");
func2({param1: "func2"});
func3("func3", 3);

オブジェクティブ指向:抽象クラス・Mixins

抽象クラス

  • Dartの抽象クラスはサブ

続きは、こちらで記載しています。
https://kazulog.fun/dev/dart-typescript-common-difference/

Discussion