A comprehensive TypeScript vector math library providing 2D, 3D, and 4D vector operations with a focus on performance and type safety.
npm install @fimbul-works/vecA high-performance TypeScript vector math library providing both functional and object-oriented APIs for 2D, 3D, and 4D vector operations with a focus on performance, type safety, and immutability.



- 🎯 Two API Styles: Choose between modern functional API (arrays) or classic OOP API (classes)
- 🛡️ Type Safe: Full TypeScript support with strict typing and array tuple types
- 📏 Multiple Distance Metrics: Euclidean, Manhattan, Chebyshev, and Minkowski
- 🎮 Graphics Ready: Homogeneous coordinates and RGB/RGBA color support
- 🧮 Comprehensive: Complete set of vector operations for game dev, graphics, and physics
- 🌳 Tree-Shakeable: Import only what you need with the functional API
``bash`
npm install @fimbul-works/vec
The functional API uses array tuples and is recommended for new projects:
`typescript
// Import the functional API
import { add2D, magnitude2D, dot2D, normalize2D } from "@fimbul-works/vec/2d";
import { add3D, cross3D } from "@fimbul-works/vec/3d";
// Type: ArrayVector2D = [number, number]
const position: ArrayVector2D = [100, 200];
const velocity: ArrayVector2D = [5, 10];
// Immutable operations return new arrays
const newPosition = add2D(position, velocity); // [105, 210]
const speed = magnitude2D(velocity); // 11.18...
// 3D operations
const v1: ArrayVector3D = [1, 2, 3];
const v2: ArrayVector3D = [4, 5, 6];
const sum = add3D(v1, v2); // [5, 7, 9]
const cross = cross3D(v1, v2); // [-3, 6, -3]
// Chain operations functionally
const result = normalize2D(add2D(position, velocity));
`
Benefits of the Functional API:
- ✅ Immutable - data never changes unexpectedly
- ✅ Tree-shakeable - smaller bundles
- ✅ Simple - just functions and arrays
- ✅ Pattern-matching ready - works with destructuring
The OOP API uses mutable classes and is maintained for backward compatibility:
`typescript
import { Vec2, Vec3, Vec4 } from "@fimbul-works/vec";
// Create and manipulate vectors
const position = new Vec2(100, 200);
const velocity = new Vec2(5, 10);
position.add(velocity); // Mutates position
// Method chaining
const result = new Vec3(1, 0, 0)
.rotateY(Math.PI / 4)
.scale(2)
.normalize();
// 3D graphics with homogeneous coordinates
const point = new Vec4(x, y, z, 1); // Point in 3D space
const vector = new Vec4(dx, dy, dz, 0); // Direction in 3D space
// Color manipulation with RGB accessors
const color = new Vec3(0.8, 0.2, 0.4);
color.r = 1.0; // Set red component
`
Complete API documentation generated by TypeDoc:
`typescript
import {
add2D, subtract2D, multiply2D, divide2D,
dot2D, cross2D,
magnitude2D, normalize2D, negate2D,
distance2D, distanceManhattan2D, distanceChebyshev2D,
lerp2D, clamp2D, limitMax2D, limitMin2D,
rotate2D, reflect2D, project2D,
angleBetween2D, angleX2D, angleY2D
} from "@fimbul-works/vec/2d";
// Vector arithmetic
const v1: ArrayVector2D = [3, 4];
const v2: ArrayVector2D = [1, 2];
add2D(v1, v2); // [4, 6] - Addition
subtract2D(v1, v2); // [2, 2] - Subtraction
multiply2D(v1, v2); // [3, 8] - Component-wise multiplication
divide2D(v1, v2); // [3, 2] - Component-wise division
// Products
dot2D(v1, v2); // 11 - Dot product
cross2D(v1, v2); // 2 - 2D cross product (returns scalar)
// Magnitude & normalization
magnitude2D(v1); // 5 - Vector length
normalize2D(v1); // [0.6, 0.8] - Unit vector
negate2D(v1); // [-3, -4] - Opposite direction
// Distance metrics
distance2D(v1, v2); // 3.606 - Euclidean distance
distanceManhattan2D(v1, v2); // 4 - Manhattan distance
distanceChebyshev2D(v1, v2); // 2 - Chebyshev distance
// Interpolation & clamping
lerp2D(v1, v2, 0.5); // [2, 3] - Linear interpolation
clamp2D(v1, 2, 8); // Keeps magnitude between 2 and 8
limitMax2D(v1, 3); // Limits magnitude to maximum of 3
limitMin2D(v1, 6); // Ensures magnitude is at least 6
// Rotation & reflection
rotate2D(v1, Math.PI / 2); // [-4, 3] - Rotate 90°
reflect2D(v1, v2); // Reflection
// Angles
angleBetween2D(v1, v2); // Angle between vectors in radians
angleX2D(v1); // Angle with x-axis
`
`typescript
// 3D point: w = 1
const point: ArrayVector4D = [x, y, z, 1];
// 3D direction: w = 0
const direction: ArrayVector4D = [dx, dy, dz, 0];
`
Migrating from the OOP API to the functional API is straightforward:
| OOP (Vec2) | Functional (2D) |
|-----------|-----------------|
| new Vec2(x, y) | [x, y] as ArrayVector2D |Vec2.add(v1, v2)
| | add2D(v1, v2) |v1.add(v2)
| | add2D(v1, v2) |v.x
| | v[0] |v.y
| | v[1] |v.magnitude
| | magnitude2D(v) |v.normalize()
| | normalize2D(v) |
Key differences:
- Functional API is immutable - returns new arrays instead of mutating
- Uses array indexing [0], [1] instead of properties .x, .y
- Functions are standalone instead of class methods
`typescript
// Functional API (Recommended)
import { add2D } from "@fimbul-works/vec/2d";
import { add3D } from "@fimbul-works/vec/3d";
import { add4D } from "@fimbul-works/vec/4d";
// OOP API (Legacy)
import { Vec2 } from "@fimbul-works/vec/vec2";
import { Vec3 } from "@fimbul-works/vec/vec3";
import { Vec4 } from "@fimbul-works/vec/vec4";
// Types
import type { ArrayVector2D } from "@fimbul-works/vec/2d";
import type { ArrayVector3D } from "@fimbul-works/vec/3d";
import type { ArrayVector4D } from "@fimbul-works/vec/4d";
``
MIT License - See LICENSE file for details.
---
Built with ⚡ by FimbulWorks