Skip to content

Instantly share code, notes, and snippets.

@tars0x9752
Last active July 4, 2021 07:00
Show Gist options
  • Select an option

  • Save tars0x9752/03b2b744a491c80078a63ce41e60b055 to your computer and use it in GitHub Desktop.

Select an option

Save tars0x9752/03b2b744a491c80078a63ce41e60b055 to your computer and use it in GitHub Desktop.
natural-number-within-ts-types
// 配列の先頭以外を抜き取る型
type Tail<T extends any[]> = T extends [any, ...infer U] ? U : []
type Zero = []
type Succ = 'Succ'
type Next<T extends Nat> = [...T, Succ] // どっちかというとNextでやってることがSuccなんだけど,,,簡単のため妥協
// 自然数 Nat
type Nat = Zero | Succ[]
// Nat の値を人間が読めるように変換する型
type NatResolver<T extends Nat> = T['length']
// Nat を数値から生成
type NatGenerator<N extends number, Acc extends Nat = Zero> = Acc['length'] extends N
? Acc
: NatGenerator<N, [Succ, ...Acc]>
// 加算
type Add<T extends Nat, U extends Nat> = [...T, ...U]
// 減算(マイナスになる場合はゼロ)
type Subtract<T extends Nat, U extends Nat> = U extends Zero ? T : Subtract<Tail<T>, Tail<U>>
// 乗算
type Multiply<T extends Nat, U extends Nat, Acc extends Nat = Zero> = U extends Zero
? Zero
: U extends [Succ]
? Add<Acc, T>
: Multiply<T, Tail<U>, Add<Acc, T>>
// 除算(切り捨て)
type Divide<T extends Nat, U extends Nat, Acc extends Nat = Zero> = U extends Zero
? never
: T extends [Succ] | Zero
? Acc
: Divide<Subtract<T, U>, U, Next<Acc>>
// 使用例
type One = Next<Zero>
type Two = Add<One, One>
type Three = Add<Two, One>
type Four = Multiply<Two, Two>
type Five = Add<Two, Three>
type Six = Multiply<Two, Three>
type Ten = NatGenerator<10>
type OneHundred = Multiply<Ten, Ten>
type n1 = NatResolver<One> // 1
type n2 = NatResolver<Two> // 2
type n3 = NatResolver<Three> // 3
type n4 = NatResolver<Four> // 4
type n5 = NatResolver<Five> // 5
type n6 = NatResolver<Six> // 6
type n10 = NatResolver<Ten> // 10
type n100 = NatResolver<OneHundred> // 100
type n24 = NatResolver<Multiply<Six, Four>> // 24
type n20 = NatResolver<Subtract<Multiply<Six, Four>, Four>> // 20
type n0_1 = NatResolver<Multiply<Zero, Six>> // 0
type n0_2 = NatResolver<Subtract<Two, Six>> // 0
type div_1 = NatResolver<Divide<Ten, Two>> // 10/2 => 5
type div_2 = NatResolver<Divide<Multiply<Six, Four>, Four>> // 24/4 => 6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment