A type-safe set of functions for 2D vector maths, working with any { x, y } object or [x, y] array. API docs.
This repo was not created because the world needed another vec2 library. It has some niche applications though, namely bridging libraries that each ship their own incompatible vector representation, which is sometimes a reality of JS/TS game development, where things like the physics engine and the renderer may come from different ecosystems.
Vector operations accept { x, y } objects and [x, y] arrays interchangeably. Transforming operations write their result into the target you pass, or into an optional destination argument, so vector instances can be reused without allocation. Queries such as dot, length and equal simply return their result, and the toArray and toObject converters each take just the representation they convert from.
The type safety goes beyond accepting both shapes. The functions are generic over the vector type you give them, so return types are inferred rather than widened. Pass an instance of your engine's point class and the result is returned and typed as that class rather than as a generic { x, y }. The optional destination works the same way, keeping allocation-free pipelines fully typed.
npm i vec2-fn
The package ships dual ESM and CJS builds, each with its own type declarations.
import { add, equal, lerp, normalize, ZERO } from "vec2-fn";
const velocity = { x: 3, y: 4 };
normalize(velocity); // velocity is now { x: 0.6000000000000001, y: 0.8 }
add(velocity, { x: 1, y: 0 }); // mutates velocity in place
equal(velocity, ZERO); // false
// Arrays work the same, and a destination keeps the inputs untouched
const out: [number, number] = [0, 0];
lerp([0, 0], [10, 10], 0.5, out); // out is [5, 5]
// Generic over your vector type, so results keep the class you pass in
class Point {
constructor(
public x = 0,
public y = 0,
) {}
}
const p = add(new Point(1, 2), { x: 3, y: 4 }); // p is typed as Point
CJS consumers can require("vec2-fn") and get the same API.
Results are raw IEEE 754 doubles with no rounding applied, the same contract as comparable vector libraries. Expect the usual floating-point artefacts (as in the normalize example above) and compare computed results with approx rather than equal. Transforming operations validate their computed components and throw on NaN or non-finite results rather than letting them propagate silently.
| Command | Purpose |
|---|---|
npm test |
Run the Vitest suite |
npm run build |
Build ESM, CJS and type declarations with tsup |
npm run typecheck |
Type-check without emitting |
npm run lint |
ESLint with warnings as errors |
npm run format |
Format with Prettier (format-check verifies) |
npm run mutation |
Stryker mutation testing |
npm run check-package |
Validate the packed tarball with publint and attw |
npm run verify-gate |
Run audit, lint, format, typecheck, tests, mutation, build and package checks |
npm run bench |
Run the runtime benchmarks (Vitest bench mode) |
npm run bench-bundle |
Measure bundle sizes and verify tree-shaking |
npm run docs |
Generate the API docs locally with typedoc |
npm run release |
Bump, changelog, tag and GitHub release via release-it |
CI runs verify-gate on every pull request and push to main. Pushing a v* tag publishes to npm from CI via trusted publishing.
feat:, fix:, chore: and so on) drive the changelog and version recommendations.main via pull request.