1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TypeScriptの型のみで四則演算を実装する

Posted at

TypeScriptの型のみで四則演算を実装する

実際の画面

cb48a796e320b2266c045eb29103a765.png

コード

そこまで高度なことはしていないと思うので、今回使った文法のみメモします。

BuildArray extends [...BuildArray, ...infer Rest]

  • BuildArray<B>で配列を生成し、...で配列の要素を展開
  • infer Restで残りの要素をRestという型変数に推論
  • BuildArray<A> extends ~でA配列は[...BuildArray<B>, ...infer Rest]の構造を持つ配列かチェックする

Array["length"]

  • 配列の長さを取得する
  • 普段のArray.lengthと同様の働きか?
/**
 * ## BuildArray
 * 
 * @param {number} L - 生成する配列の長さ
 * @param {unknown[]} A - 生成された配列
 * 
 * @example
 * type Result = BulidArray(3) // [unknown, unknown, unknown]
 * 
 * @description
 * 引数Lと同じ長さの配列を生成する
 * 配列AがLと等しくなるまで再帰的に繰り返す
 */
type BuildArray<L extends number, A extends unknown[] = []> = A["length"] extends L ? A : BuildArray<L, [...A, unknown]>

/**
 * ## Num(数値型)
 * 
 * @param {number} N - 数値型
 * @returns {number} 入力された数値型をそのまま返す
 * 
 * @example 
 * type Result = Num<5> // 5
 * 
 * @description
 * 入力された数値型をそのまま返す
 */
type Num<N extends number> = N;

/**
 * LessThan(数値の比較)
 * 
 * @param {number} A - 比較対象元
 * @param {number} B - 比較対象
 * 
 * @example
 * type Result = LessThan<5, 0> // true
 * 
 * @description
 * AがBより小さい場合trueを返す
 * それ以外はfalseを返す
 * 以下の動作を表している
 * a > b ? true : false
 */
type LessThan<A extends number, B extends number> =
  A extends B
  ? false
  : BuildArray<A> extends [...BuildArray<B>, ...infer Rest]
  ? false
  : true
  
/**
 * ## Add - 加算
 * 
 * @param {number} A - 被加数
 * @param {number} B - 加数
 * @returns {number} 加算結果を数値型として返す
 * 
 * @example
 * // 3 + 4 = 7
 * type Result = Add<3, 4> // 7
 * 
 * @description
 * 1. 引数A, Bの長さの配列を生成
 * 2. 生成した配列を結合する
 * 3. 結合した配列の長さが加算の結果となる
 */
type Add<A extends number, B extends number> = [...BuildArray<A>, ...BuildArray<B>]["length"]

/**
 * ## Sub(減算)
 * 
 * @param {number} A - 被減数
 * @param {number} B - 減数
 * @returns {number} 減算結果を数値型として返す
 * 
 * @example
 * type Result = Sub<10, 5> // 5
 * 
 * @description
 * #### 引数Aが引数Bより大きい場合
 * 1. 引数Aの長さの配列から引数Bの配列の長さ分を取り除いた残りの部分Restを返す
 * 
 * #### 引数Bが引数Aより大きい場合
 * 1. 引数Bの長さの配列から引数Aの配列の長さ分を取り除いた残りの部分Restを返す
 */
type Sub<A extends number, B extends number> = BuildArray<A> extends [...BuildArray<B>, ...infer Rest]
  ? Rest['length']
  : BuildArray<B> extends [...BuildArray<A>, ...infer Rest]
  ? Rest["length"]
  : never

/**
 * Multi(乗算)
 * 
 * @param {number} A - 被乗数
 * @param {number} B - 乗数
 * @returns {number} 乗算結果を数値型として返す
 * 
 * @example
 * type Result = Multi<4, 9> // 36
 * 
 * @description
 * 再帰的にBを1ずつ減らして結果RにAを足す
 */
type Multi<A extends number, B extends number, R extends number = 0> =
  A extends 0 ?
  R : B extends 0 ?
  R : Multi<A, Sub<B, 1>, Add<R, A> extends number ? Add<R, A> : never>;


/**
 * ## Div(除算)
 * 
 * @param {number} A - 被除数
 * @param {number} B - 除数
 * @returns {number} 除算結果を数値型として返す
 * 
 * @example
 * type Result = Div<24, 8> // 3
 * 
 * @description
 * 被除数が0になるまで再帰的に減算を繰り返し、結果Rに1ずつ足していく
 */
type Div<A extends number, B extends number, R extends number = 0> =
  A extends 0 ?
  R : B extends 0 ?
  R : LessThan<A, B> extends false ?
  Div<Sub<A, B>, B, Add<R, 1> extends number ? Add<R, 1> : never> : "計算できません"


// 計算
type add42 = Add<4, 2> // 6
type sub54 = Sub<5, 4> // 1
type sub105 = Sub<10, 5> // 5
type multi04 = Multi<0, 4> // 0
type multi40 = Multi<4, 0> // 0
type multi14 = Multi<1, 4> // 4
type multi101 = Multi<10, 1> // 10
type multi52 = Multi<5, 2> // 10
type multi49 = Multi<4, 9> // 36
type multi37 = Multi<3, 7> // 21
type div205 = Div<20, 5> // 4
type div248 = Div<24, 8> // 3
type div824 = Div<8, 28> // 計算できません

最後に

間違っていることがあれば、コメントに書いていただけると幸いです。
よろしくお願いいたします。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?