npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ts-arithmetic

v0.1.1

Published

Type Level Arithmetic

Downloads

3,243

Readme

Contributors Forks Stargazers Issues MIT License

About The Project

Product Name Screen Shot

ts-arithmetic allows you to perform all the basic arithmetic operations at the Type Level, without any of the usual limitations associated with the dreaded "type instantiation is excessively deep and possibly infinite" TypeScript error. All other existing utilities are limited to small positive integers. ts-arithmetic does not have this limitation.

Built With

  • TypeScript

Getting Started

Prerequisites

  • npm install typscript@^4.8.2 --save-dev

Installation

  • npm install ts-arithmetic --save-dev

Usage

Core

import { Add, Subtract, Multiply, Divide, Pow, Compare, Mod } from 'ts-arithmetic'
// Check the docs below for more

// Add any two numbers
type AddExample = Add<1024, 256>
// 1280

// Subtract any two numbers
type SubtractExample = Subtract<400, 1000>
// -600

// Multiply any two numbers
type MultiplyExample = Multiply<25, 50>
// 1250

// Divide any two numbers
type DivideExample = Divide<-1, 800>
// -0.00125

// Raise a number to an integer power
type PowExample = Pow<5, 7>
// 78125

// Compare any two numbers (same rules as JavaScript Array.sort())
type CompareExample = Compare<123456, 20>
// 1

// Get the JavaScript mod (i.e. remainder)
type ModExmaple = Mod<87, 7>
// 3

Type Utility Reference

Arithmetical Operations

Comparison Operations

Other Checks

Sign

Parity

Number Type

Bit Operations


General Operation Semantics

All of the operations behave pretty much how you would expect them to. They all accept positive/negative integers/fractions. There are a few things to note about never, number, unions of numeric literals and literals given in scientific notation (e.g. 8.5e-15)

never

Passing never in for any parameter will always resolve to never.

Unions of numeric literals

Every type operation will distribute over their parameters as though you called the operation once on each member of the provided union type. e.g.

type ThreeOrFour = Add<1, 2|3> // resolves to 3 | 4

type NegFiveOrTen = Negate<5|-10> // reolves to -5 | 10

For operations that take 2 parameters, if a union type is provided for both parameters, then it will be as though you called the operation on each combination of members of the union types. e.g.

type CartesianAdd = Add<3|4, 10|20> // resolves to 13 | 23 | 14 | 24

number

Most of the time, passing number in for any parameter will resolve to number - though not always.

The answer for any specific case can always be worked out if you think of number as meaning the union of all numeric literals i.e.

type number = ... | -1 | -0.999...9 | -0.999...8 | ... | 0 | 0.000...1 | 0.000...2 | ... | 1 | ...

The type utilities will always return the most restrictive union of the results possible.

For example, 0 * X = 0 for all X. So:

type Zero = Multiply<0, number> // resolves to 0

Or for any of the types that already return some subset of number, then that entire subset will be returned. e.g.

type ZeroOrOne = IsPositive<number> // resolves to 0 | 1

But for 1 + X, there is no meaningfull way to simplify down in the same way. So:

type Useless = Add<1, number> // resolves to number

Scientific Notation

Passing in a numeric literal N where -1 < N < 1 in scientific notation e.g. 8.5e-10 will work just fine.

However there is an issue with large numeric literals given in scientific notation e.g. 1e+21. For N where Abs(N) < 1e+21, typescript will automatically resolve this to its expanded form (e.g. 100000000000000000000) so everything will work as normal. But exceeding this limit will cause typescript to resolve the literal in scientific notation.

type Big1 = 1.0000001e+20 // typescript resolves this to 100000010000000000000
type Big2 = 1e+20 // typescript resolves this to 100000000000000000000
type BigSubtract = Subtract<Big1, Big2> // 10000000000000

type TooBig1 = 1.0000001e+21 // typescript resolves this exactly as it appears, 1.0000001e+21
type TooBig2 = 1e+21 // typescript resolves this exactly as it appears, 1e+21
type TooBigSubtract = Subtract<TooBig1, TooBig2> // never

This notation can be supported (and might in the future) but it currently is not.

Add

Add any two numeric literals. It works exactly how you expect it to.

type NormalExample = Add<75, 25> // 100

type NegativeFractionsExample = Add<-1.5, 0.25> // -0.25

type UnionExample = Add<75|5, 25> // 100 | 30

Subtract

Subtract a numeric literal from another.

type NormalExample = Subtract<200, 50> // 150

type NegativeFractionsExample = Subtract<-35.5, 1.75> // -37.25

type UnionExample = Subtract<100|70, 20> // 80 | 50

Multiply

Multiply any two numeric literals.

type NormalExample = Multiply<25, 25> // 625

type NegativeFractionsExample = Multiply<-0.005, 20> // -0.1

type UnionExample = Multiply<2|3, 4> // 8 | 12

type Zero = Multiply<0, 21212> // 0

type AlsoZero = Multiply<0, number> // 0

Divide

Divide a numeric literal by another.

type NormalExample = Divide<25, 5> // 25

type NegativeFractionsExample = Divide<-0.005, 20> // -0.00025

type UnionExample = Divide<100|50, 5> // 20 | 10

type NotPossible = Divide<10, 0> // never

type AbsorbedNever = Divide<10, 2|0> // 5 | never --> 5

// even though number "contains" 0, since Divide distibutes, the never is
// absorbed into the resulting union just like the above example
type Zero = Divide<0, number> // 0

Pow

Raise a numeric literal to an integer exponent. The limitation of integer exponents will be lifted soon.

type NormalExample = Pow<2, 10> // 1024

type UnionExample = Pow<2|3, 10> // 1024 | 59049

type ReciprocalExample = Pow<20.5, -2> // 0.002379535990481

type AlwaysOne = Pow<10, 0> // 1

type AlsoAlwaysOne = Pow<number, 0> // 1

type NotPossible = Pow<0, -1> // never

type AbsorbedNever = Pow<0, -1|5> // never | 0 --> 0

// even though number "contains" negative values, since Pow distibutes, the never is
// absorbed into the resulting union just like the above example
type Zero = Pow<0, number> // 0

type AndAlsoAlwaysOne = Pow<1, number> // 1

type OneOrMinusOne = Pow<-1, 2|3> // 1 | -1

type AlsoOneOrMinusOne = Pow<-1, number> // 1 | -1

type Imaginary = Pow<-1, 0.5> // never

type ZeroOrOne = Pow<0|1, number> // 0 | 1

type AsExpected0 = Pow<0, 0.5> // 0
type AsExpected1 = Pow<1, 0.5> // 1

type NotAvailableYet = Pow<2, 0.5> // never

type AbsorbedNotAvailableYetNever = Pow<2, 0.5|2> // never | 4 --> 4

Mod

Perform a JavaScript remainder (%) operation on any two numeric literals.

type NormalExample = Mod<7, 2> // 1

type UnionExample = Mod<20|19, 10> // 0 | 9

type NegativeExample = Mod<-7, 2> // -1

type FractionExample = Mod<19.99, 7.5> // 4.99

type NotPossible = Mod<5, 0> // never

type ZeroRemainder = Mod<20, 1> // 0

type FractionRemainder = Mod<20.555, 1> // 0.555

type AlwaysZero = Mod<0, 45> // 0

type ReallyItsAlwaysZero = Mod<0, number> // 0

type AbsorbedNever = Mod<10, 3|0> // 1 | never --> 1

Negate

Negate a numeric literal.

type NormalExample = Negate<-12345> // 12345

type UnionExample = Negate<-1 | 2> // 1 | -2

type NumberExample = Negate<number> // number

Abs

Get the absolute value of a numeric literal.

type NormalExample = Abs<-12345> // 12345

type UnionExample = Abs<-1 | 2> // 1 | 2

type NumberExample = Abs<number> // number

Compare

Compare any two numeric literals. Returns -1 | 0 | 1 as per rules in Array.sort().

For Compare<X, Y>

  • -1 --> X is less than Y
  • 0 --> X and Y are equal
  • 1 --> X is greater than Y
type NormalExample1 = Compare<5, 10> // -1
type NormalExample2 = Compare<5, 5> // 0
type NormalExample3 = Compare<10.1234, -5.111> // 1

type UnionExample = Compare<5|10, 7> // -1 | 1

type NumberExample = Compare<number, 7> // -1 | 0 | 1

Gt

Perform a greater than comparison on any two numeric literals.

  • 1 --> X > Y
  • 0 --> X <= Y
type NormalExample1 = Gt<5, 10> // 0
type NormalExample2 = Gt<5, 5> // 0
type NormalExample3 = Gt<10.1234, -5.111> // 1

type UnionExample = Gt<5|10, 7> // 0 | 1

type NumberExample = Gt<number, 7> // 0 | 1

Lt

Perform a less than comparison on any two numeric literals.

  • 1 --> X < Y
  • 0 --> X >= Y
type NormalExample1 = Lt<5, 10> // 1
type NormalExample2 = Lt<5, 5> // 0
type NormalExample3 = Lt<10.1234, -5.111> // 0

type UnionExample = Lt<5|10, 7> // 0 | 1

type NumberExample = Lt<number, 7> // 0 | 1

Eq

Perform a equality comparison on any two numeric literals.

  • 1 --> X === Y
  • 0 --> X !== Y
type NormalExample1 = Eq<5, 10> // 0
type NormalExample2 = Eq<5, 5> // 1

type UnionExample = Eq<5|10, 10> // 0 | 1

type NumberExample = Eq<number, 7> // 0 | 1

GtOrEq

Perform a greater than or equal to comparison on any two numeric literals.

  • 1 --> X >= Y
  • 0 --> X < Y
type NormalExample1 = GtOrEq<5, 10> // 0
type NormalExample2 = GtOrEq<5, 5> // 1
type NormalExample3 = GtOrEq<10.1234, -5.111> // 1

type UnionExample = GtOrEq<5|7|10, 7> // 0 | 1

type NumberExample = GtOrEq<number, 7> // 0 | 1

LtOrEq

Perform a less than or equal to comparison on any two numeric literals.

  • 1 --> X <= Y
  • 0 --> X > Y
type NormalExample1 = LtOrEq<5, 10> // 1
type NormalExample2 = LtOrEq<5, 5> // 1
type NormalExample3 = LtOrEq<10.1234, -5.111> // 0

type UnionExample = LtOrEq<5|7|10, 7> // 0 | 1

type NumberExample = LtOrEq<number, 7> // 0 | 1

Max

Get the greatest of two numeric literals.

type NormalExample1 = Max<5, 10> // 10
type NormalExample2 = Max<50, 5> // 50
type NormalExample3 = Max<10.1234, -5.111> // 10.1234

type UnionExample = Max<5|8|10, 7> // 7 | 8 | 10

type NumberExample = Max<number, 7> // number

Min

Get the smallest of two numeric literals.

type NormalExample1 = Min<5, 10> // 5
type NormalExample2 = Min<50, 5> // 5
type NormalExample3 = Min<10.1234, -5.111> // -5.111

type UnionExample = Min<5|8|10, 7> // 5 | 7

type NumberExample = Min<number, 7> // number

IsPositive

Check if a numeric literal is positive.

type NormalExample = IsPositive<-12345> // 0

type UnionExample = IsPositive<-1 | 2> // 0 | 1

type NumberExample = IsPositive<number> // 0 | 1

IsNegative

Check if a numeric literal is negative.

type NormalExample = IsNegative<-12345> // 1

type UnionExample = IsNegative<-1 | 2> // 0 | 1

type NumberExample = IsNegative<number> // 0 | 1

IsOdd

Check if a numeric literal is odd.

type NormalExample = IsOdd<123> // 1

type FractionExample = IsOdd<3.5> // never

type UnionExample = IsOdd<2 | 3> // 0 | 1

type NumberExample = IsOdd<number> // 0 | 1

IsEven

Check if a numeric literal is even.

type NormalExample = IsEven<123> // 0

type FractionExample = IsEven<3.5> // never

type UnionExample = IsEven<2 | 3> // 0 | 1

type NumberExample = IsEven<number> // 0 | 1

IsInt

Check if a numeric literal is an integer.

type NormalExample = IsInt<123> // 1

type FractionExample = IsInt<3.5> // 0

type UnionExample = IsInt<2 | 3.5> // 0 | 1

type NumberExample = IsInt<number> // 0 | 1

IsNotInt

Check if a numeric literal is not an integer.

type NormalExample = IsNotInt<123> // 0

type FractionExample = IsNotInt<3.5> // 1

type UnionExample = IsNotInt<2 | 3.5> // 0 | 1

type NumberExample = IsNotInt<number> // 0 | 1

And

Perform an AND operation on two Bits.

type OneAndOne = And<1, 1> // 1
type OneAndZero = And<1, 0> // 0
type ZeroAndOne = And<0, 1> // 0
type ZeroAndZero = And<0, 0> // 0

type UnionExample = And<1 | 0, 1> // 0 | 1

Or

Perform an OR operation on two Bits.

type OneOrOne = Or<1, 1> // 1
type OneOrZero = Or<1, 0> // 1
type ZeroOrOne = Or<0, 1> // 1
type ZeroOrZero = Or<0, 0> // 0

type UnionExample = Or<1 | 0, 1> // 1

Xor

Perform an XOR operation on two Bits.

type OneXorOne = Xor<1, 1> // 0
type OneXorZero = Xor<1, 0> // 1
type ZeroXorOne = Xor<0, 1> // 1
type ZeroXorZero = Xor<0, 0> // 0

type UnionExample = Xor<1 | 0, 1> // 0 | 1

Not

Perform an NOT operation on a Bit.

type NotZero = Not<0> // 1
type NotOne = Not<1> // 0

type UnionExample = Not<0 | 1> // 0 | 1

See the open issues for a full list of proposed features (and known issues).

Roadmap

  • Support big numbers e.g. 8.5e+50

License

Distributed under the MIT License. See LICENSE for more information.

Contact

Project Link: https://github.com/arielhs/ts-arithmetic