タイプスクリプトによる代数的データ型



関数型プログラミング言語は素晴らしい.彼らは多くの華麗なデザインの決定を持って、最も主流のものはAlgebraic Data Type (ADT)とパターンマッチングです.
単純なreasonmlの例
/* Algebraic Data Type */
type coolString = 
  | Uppercase(string)
  | Concat(string, string)
  | Empty;

/* pattern matching */
let string_of_cool_string = fun
  | Uppercase(str) => String.uppercase_ascii(str)
  | Concat(str1, str2) => str1 ++ str2
  | Empty => ""
あなたは追加データ/ペイロードとペイロードフルenumsによってスイッチとしてパターンマッチングとenumとしてADTを考えることができます.
ナイーブタイプスクリプトの実装は以下のようになります:
type UpperCase = {
  key: 'UPPERCASE',
  value: string,
}

type Concat = {
  key: 'CONCAT',
  value: [string, string],
}

type Empty = {
  key: 'EMPTY',
}

const makeUpperCase = (value: string): UpperCase => ({
  key: 'UPPERCASE',
  value,
});

const makeConcat = (value: [string, string]): Concat => ({
  key: 'CONCAT',
  value,
});

const makeEmpty = (value: string): Empty => ({
  key: 'EMPTY',
});

type CoolString = UpperCase | Concat | Empty;

const match = (action: CoolString): string => {
  switch (action.key) {
    case 'UPPERCASE':
      return action.value.toUpperCase();
    case 'CONCAT':
      return action.value.join('');
    case 'EMPTY':
      return '';
  }
}
ご覧のように、タイプスクリプトのバージョンはとても冗長です.この記事の目的は、すべてのシンプルで、すべての静的なタイプの機能を持っている間、コードの行の数を下げるための可能な解決策の1つを提示することです.
最初に、オプションを作成するADTオプションと機能を表す簡単な型を書きます
type Option<Key extends string, Value = undefined> = {
  key: Key,
  value: Value,
};

const makeOption = <Key extends string, Value = undefined>(
  key: Key,
) => (
  value: Value,
): Option<Key, Value> => ({
  key,
  value,
});
使用するコードは以下のようになります.
const Upper = makeOption<'upper', string>('upper')
const Concat = makeOption<'concat', [string, string]>('concat');
const Empty = makeOption<'empty'>('empty');

type CoolString
  = ReturnType<typeof Upper>
  | ReturnType<typeof Concat>
  | ReturnType<typeof Empty>

const match = (coolString: CoolString): string => {
  switch (coolString.key) {
    case 'upper':
      return coolString.value.toUpperCase();
    case 'concat':
      return coolString.value.join('');
    case 'empty':
      return '';
  }
}
このように、私たちはボイラープレートを抽出したので、ADTパターンは非常にクリーナーになりました.