import {
Byte, Num, Add, Sub, Mul, Div, Mod, Eq, Lt, Gt, Lte, Gte, Lsh, Rsh, And, Xor, Or, Not
} from './ts-8-bit'
// Arithmetic
type A = Num< Add < Byte<12>, Byte<22> > > // + type A = 34
type B = Num< Sub < Byte<47>, Byte<12> > > // - type B = 35
type C = Num< Mul < Byte<31>, Byte<4> > > // * type C = 124
type D = Num< Div < Byte<16>, Byte<8> > > // / type D = 2
type E = Num< Mod < Byte<19>, Byte<4> > > // % type E = 3
// Equality
type F = Eq < Byte<10>, Byte<10> > // == type F = true
type G = Lt < Byte<10>, Byte<10> > // < type G = false
type H = Gt < Byte<20>, Byte<10> > // > type H = true
type I = Lte< Byte<10>, Byte<10> > // <= type I = true
type J = Gte< Byte<20>, Byte<10> > // >= type J = true
// Bitwise
type K = Num< Rsh < Byte<64>, 3 > > // >> type K = 8
type L = Num< Lsh < Byte<23>, 2 > > // << type L = 92
type M = Num< Or < Byte<33>, Byte<7> > > // | type M = 39
type N = Num< And < Byte<12>, Byte<5> > > // & type N = 4
type O = Num< Xor < Byte<22>, Byte<17 > > > // ^ type O = 7
type P = Num< Not < Byte<253> > > // ! type P = 2
ts-8-bit is an experimental library that does 8-bit arithmetic on TypeScript's type system. It does so by applying bitwise operations on tuples of length 8 (1 byte) and leverages TypeScript conditional type inference to give the result. This project was written as a exercise in TypeScript and is offered as is for anyone who may find it of use.
Requires TypeScript 4.1.2 and above. Example link here.
License MIT
The following demonstrates basic usage.
import { Byte, Num, Add, Sub, Mod } from './ts-8-bit'
// ------------------------------------------------------------------------
//
// Use Byte<T> and Num<T> to map between bytes and numbers
//
// ------------------------------------------------------------------------
type A = Byte<127> // type A = [1, 1, 1, 1, 1, 1, 1, 0]
type B = Num<[1, 1, 1, 1, 1, 1, 1, 0]> // type B = 127
type C = Num< Byte<55> > // type C = 55
// ------------------------------------------------------------------------
//
// ... with math done exclusively on bytes ...
//
// ------------------------------------------------------------------------
type D = Add< // type D = [0, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 1, 1, 1, 0]
>
// ------------------------------------------------------------------------
//
// ... but can be remapped this way ...
//
// ------------------------------------------------------------------------
type E = Num< Add< Byte<127>, Byte<127> > > // type E = 254
// ------------------------------------------------------------------------
//
// ... and used for stuff like ...
//
// ------------------------------------------------------------------------
type FizzBuzz<T extends Byte<any>> =
Mod<T, Byte<5>> extends Byte<0> ?
Mod<T, Byte<3>> extends Byte<0> ? 'fizzbuzz' : 'buzz' :
Mod<T, Byte<3>> extends Byte<0> ? 'fizz' : ""
type T1 = FizzBuzz< Byte<1> > // ""
type T2 = FizzBuzz< Byte<2> > // ""
type T3 = FizzBuzz< Byte<3> > // "fizz"
type T4 = FizzBuzz< Byte<4> > // ""
type T5 = FizzBuzz< Byte<5> > // "buzz"
type T6 = FizzBuzz< Byte<6> > // "fizz"
// ... etc ...
type T15 = FizzBuzz< Byte<15> > // "fizzbuzz"
// ------------------------------------------------------------------------
//
// ... or something more elaborate ...
//
// ------------------------------------------------------------------------
type IsPrimeOp<
A extends [Bit, Bit, Bit, Bit, Bit, Bit, Bit, Bit],
B extends [Bit, Bit, Bit, Bit, Bit, Bit, Bit, Bit]
> = Num<B> extends 1 ? true :
Num<Mod<A, B>> extends 0 ? false :
IsPrimeOp<A, Sub<B, Byte<1>>>
type IsPrime<
A extends [Bit, Bit, Bit, Bit, Bit, Bit, Bit, Bit]
> = IsPrimeOp<A, Sub<A, Byte<1>>>
type P3 = IsPrime< Byte<3> > // true
type P4 = IsPrime< Byte<4> > // false
type P5 = IsPrime< Byte<5> > // true
type P6 = IsPrime< Byte<6> > // false
type P7 = IsPrime< Byte<7> > // true
type P8 = IsPrime< Byte<8> > // false
type P9 = IsPrime< Byte<9> > // false
type P10 = IsPrime< Byte<10> > // false
type P11 = IsPrime< Byte<11> > // true
type P12 = IsPrime< Byte<12> > // false
type P13 = IsPrime< Byte<13> > // true
type P14 = IsPrime< Byte<14> > // false
type P15 = IsPrime< Byte<15> > // false
type P16 = IsPrime< Byte<16> > // false
type P17 = IsPrime< Byte<17> > // true - pushing recursion limits here
type P18 = IsPrime< Byte<18> > // false