Shared
Cross-cutting helpers and type utilities every other `std` module builds on: guards, `match`, `pipe`, deep merge, dotted paths, and more.
@ozaco/std/sharedshared is the dependency-free foundation of the standard library — the small, general-purpose helpers and types that result, effect, plugin, codec and logger all reuse, kept in one place so they never import each other in a cycle.
On the runtime side it ships type guards (isString, isObject, isPromise, isGenerator, …), a fluent pattern matcher (match), left-to-right function composition that transparently threads promises (pipe), immutable object helpers (deepMerge, getPath/setPath/unsetPath, flatten), string and error formatting (kebabToPascal, createTags, serializeError), lazy promises, a bitflag test, a binary-heap PriorityQueue, and synchronous Standard Schema validation (validateSync).
On the type side it exports the primitives the rest of the library is written against — AnyType, EmptyType, Primitive, LiteralUnion, Writable/WriteableDeep, ExplicitObject, the Pipe and MatchBuilder shapes, and the vendor-neutral StandardSchemaV1 / StandardJSONSchemaV1 interfaces used for schema interop.
Guards
Runtime type predicates that narrow `unknown`.
isString
Narrow a value to `string`.
function isString(value: unknown): value is stringisNumber
Narrow a value to `number`.
function isNumber(value: unknown): value is numberisBoolean
Narrow a value to `boolean`.
function isBoolean(value: unknown): value is booleanisUndefined
Narrow a value to `undefined`.
function isUndefined(value: unknown): value is undefinedisFunction
Narrow a value to a callable `Function`.
function isFunction(value: unknown): value is FunctionisObject
Narrow a value to a non-null, non-array object.
function isObject(value: unknown): value is Record<string, unknown>isArray
Narrow a value to an array.
function isArray<T>(value: unknown): value is T[]isPromise
Narrow a value to a thenable (`PromiseLike`).
function isPromise(value: unknown): value is PromiseLike<any>isGenerator
Narrow a value to a synchronous `Generator`.
function isGenerator(value: unknown): value is Generator<any, any>isAsyncGenerator
Narrow a value to an `AsyncGenerator`.
function isAsyncGenerator(value: unknown): value is AsyncGenerator<any, any>isAsyncIterable
Narrow a value to an `AsyncIterable`.
function isAsyncIterable(value: any): value is AsyncIterable<unknown>isArrayBuffer
Narrow a value to an `ArrayBuffer`.
function isArrayBuffer(value: unknown): value is ArrayBufferisArrayBufferView
Narrow a value to any `ArrayBufferView` (typed array or `DataView`).
function isArrayBufferView(value: unknown): value is ArrayBufferViewUtilities
Functional, object, string and collection helpers.
match
Build a fluent, type-narrowing pattern matcher over a value.
function match<const T>(value: T): MatchBuilder<T, T, never>
// MatchBuilder chains:
.with(schema, handler) // match by Standard Schema, narrowing the remaining type
.when(predicate, handler) // match by predicate/type-guard
.otherwise(handler) // fallback, returns the result
.exhaustive() // require all cases covered (compile-time)
.run() // evaluate, returning the result or nullCases are evaluated top-to-bottom: the first with schema that validates or when predicate that passes wins, and its handler (a function, or a bare value for when) produces the result. .otherwise supplies a fallback, .exhaustive requires the union to be fully covered (throwing at runtime if nothing matches), and .run returns null when no case matches.
import { match } from '@ozaco/std/shared'
const label = match(status)
.when((s): s is 200 => s === 200, () => 'ok')
.when((s) => s >= 500, () => 'server error')
.otherwise(() => 'unknown')pipe
Thread a value left-to-right through functions, awaiting promises between steps.
const pipe: Pipe
// Pipe is a set of overloads (1 → 26 functions):
function pipe<A>(a: A): A
function pipe<A, B>(a: A, ab: (a: Awaited<A>) => B): B
function pipe<A, B, C>(a: A, ab: (a: Awaited<A>) => B, bc: (b: Awaited<B>) => C): C
// …and so onApplies each function to the running value in order. If any step is a promise, the next function is chained with .then, so an async step turns the whole pipeline async — each subsequent function receives the Awaited value.
import { pipe } from '@ozaco/std/shared'
const doubled = pipe(
' 42 ',
(s) => s.trim(),
(s) => Number(s),
(n) => n * 2,
) //=> 84deepMerge
Recursively merge plain objects left → right, cloning nested objects and returning a fresh tree.
function deepMerge<T extends Record<string, any>>(
...sources: (Partial<T> | undefined)[]
): TLater sources win. Nested plain objects merge deeply; arrays and primitives are replaced wholesale. An undefined value never overrides an earlier one. Inputs are never mutated — nested objects are cloned so the result never aliases a source (arrays are shared by reference).
import { deepMerge } from '@ozaco/std/shared'
deepMerge(
{ a: 1, nested: { x: 1 } },
{ b: 3, nested: { y: 2 } },
) //=> { a: 1, b: 3, nested: { x: 1, y: 2 } }getPath
Read a dotted key (`a.b.c`) from a nested object.
function getPath<T = unknown>(obj: Record<string, any>, path: string): T | undefinedReturns undefined if any segment along the path is missing or non-object.
import { getPath } from '@ozaco/std/shared'
getPath({ a: { b: 1 } }, 'a.b') //=> 1
getPath({ a: {} }, 'a.b.c') //=> undefinedsetPath
Set a dotted key, returning a new object with intermediates created/cloned.
function setPath<T extends Record<string, any>>(
obj: T,
path: string,
value: unknown,
): TImmutable: the original object and untouched branches are preserved; only the path down to the leaf is cloned.
import { setPath } from '@ozaco/std/shared'
setPath({ a: { b: 1 } }, 'a.c', 2) //=> { a: { b: 1, c: 2 } }unsetPath
Remove a dotted key, returning a new object (a no-op copy if the path is absent).
function unsetPath<T extends Record<string, any>>(obj: T, path: string): TflattenEntries
Flatten a nested object to leaf `{ key, value }` entries with dotted keys.
function flattenEntries(obj: Record<string, any>, prefix?: string): FlatEntry[]Recurses into nested plain objects; arrays are treated as leaf values.
import { flattenEntries } from '@ozaco/std/shared'
flattenEntries({ a: { b: 1 }, c: 2 })
//=> [{ key: 'a.b', value: 1 }, { key: 'c', value: 2 }]flatten
Flatten a nested object to dotted keys, keeping only function-valued leaves.
function flatten(obj: Record<string, any>, prefix?: string): Record<string, any>Recurses into nested plain objects and collects only function leaves under their dotted key path (non-function, non-object values are dropped). Used internally to flatten nested action maps in the plugin system.
kebabToPascal
Convert a `kebab-case` string to `PascalCase`, at the value and type level.
function kebabToPascal<S extends string>(s: S): KebabToPascal<S>import { kebabToPascal } from '@ozaco/std/shared'
kebabToPascal('no-match') //=> 'NoMatch'serializeError
Render any thrown value into a stable, human-readable string.
function serializeError(error: unknown): stringStrings pass through; Errors become name: message (with (code) appended when present); null/undefined stringify; other objects are JSON.stringifyd (falling back to Object.prototype.toString); everything else is String(...).
validateSync
Validate a value against a Standard Schema synchronously, as a `Result`.
function validateSync<Schema extends StandardSchemaV1>(
schema: Schema,
value: unknown,
): Result<
StandardSchemaV1.InferOutput<Schema>,
readonly StandardSchemaV1.Issue[]
>Works with any Standard Schema library (zod, valibot, arktype, …). Returns succeed(output) on success or fail(issues) with the schema’s raw issues, so the caller keeps control of formatting. Async schemas cannot run here — a failure is returned advising validate (a Future) from @ozaco/std/effect.
import { validateSync } from '@ozaco/std/shared'
import { isSuccess } from '@ozaco/std/result'
const result = validateSync(userSchema, input)
if (isSuccess(result)) {
result.value // typed schema output
}lazyPromise
Create a promise whose executor runs only when it is first awaited.
function lazyPromise<T, E>(
resolver: (resolve: (value: T) => void, reject: (error: E) => void) => void,
): Promise<T>The resolver is deferred until the first then/catch/finally, then memoized, so an unawaited lazyPromise never does work. The returned object is Promise-shaped and interoperates with await.
lazyPromiseWithResolvers
A lazy counterpart to `Promise.withResolvers`, recording a settle even before anyone awaits.
function lazyPromiseWithResolvers<T>(): PromiseWithResolvers<T>Returns { promise, resolve, reject } where promise is a lazyPromise. Calling resolve/reject before the promise is awaited records the outcome (first settle wins); it is replayed when the promise is eventually awaited.
import { lazyPromiseWithResolvers } from '@ozaco/std/shared'
const { promise, resolve } = lazyPromiseWithResolvers<number>()
resolve(42) // settles before anyone awaits
await promise //=> 42hasFlag
Test whether a bit (or mask) is set within a numeric bitfield.
function hasFlag(flags: number, flag: number): booleanimport { hasFlag } from '@ozaco/std/shared'
hasFlag(0b1010, 0b0010) //=> truePriorityQueue
A binary-heap priority queue; lower priority numbers pop first, ties FIFO within a tier.
class PriorityQueue<T> {
push(priority: number, item: T): void
pop(): T | undefined
}Items sharing a priority are grouped into a tier and dequeued first-in-first-out; tiers are ordered by a min-heap so pop always returns an item from the lowest priority number present. push and pop are amortized O(log n) in the number of distinct priorities.
import { PriorityQueue } from '@ozaco/std/shared'
const q = new PriorityQueue<string>()
q.push(10, 'low')
q.push(1, 'high')
q.pop() //=> 'high' (lowest priority number wins)Types
Type-level primitives and interop shapes.
AnyType
An intentional `any` escape hatch, isolated behind a named alias.
type AnyType = anyEmptyType
The empty object type `{}` (any non-nullish value).
type EmptyType = {}AnyFunction
A unary function accepting and returning `any`.
type AnyFunction = (value: any) => anyPrimitive
The union of all JavaScript primitive types.
type Primitive = null | undefined | string | number | boolean | symbol | bigintLiteralUnion
A literal union that still autocompletes but accepts any value of the base type.
type LiteralUnion<LiteralType, BaseType extends Primitive> =
| LiteralType
| (BaseType & Record<never, never>)type Color = LiteralUnion<'red' | 'green', string>
// suggests 'red' | 'green' but accepts any stringWritable
Strip `readonly` from every top-level property of `T`.
type Writable<T> = { -readonly [P in keyof T]: T[P] }WriteableDeep
Recursively strip `readonly` throughout `T`.
type WriteableDeep<T> = { -readonly [P in keyof T]: WriteableDeep<T[P]> }KnownKeys
The explicitly declared keys of `T`, excluding index signatures.
type KnownKeys<T> = keyof {
[K in keyof T as string extends K
? never
: number extends K
? never
: symbol extends K
? never
: K]: T[K]
}ExplicitObject
Pick only the explicitly declared keys of `T` (drops index signatures).
type ExplicitObject<T> = Pick<T, KnownKeys<T> & keyof T>KebabToPascal
Type-level `kebab-case` → `PascalCase` string transform.
type KebabToPascal<S extends string> = S extends `${infer Head}-${infer Tail}`
? `${Capitalize<Head>}${KebabToPascal<Tail>}`
: Capitalize<S>IsPromise
Resolve to `true` when `T` is a `Promise`, else `false`.
type IsPromise<T> = T extends Promise<any> ? true : falseIsPromiseStrict
Like `IsPromise`, but a bare `object`/`{}` resolves to `false`.
type IsPromiseStrict<T> = object extends T
? false
: T extends Promise<any>
? true
: falseGuardValue
Extract the narrowed (or argument) type from a type-guard/predicate function.
type GuardValue<fn> = fn extends (value: any) => value is infer b
? b
: fn extends (value: infer a) => unknown
? a
: neverPromiseWithResolvers
The return shape of `Promise.withResolvers` for `T`.
type PromiseWithResolvers<T> = ReturnType<typeof Promise.withResolvers<T>>FlatEntry
A flattened leaf produced by `flattenEntries`: a dotted key and its value.
interface FlatEntry {
key: string
value: unknown
}MatchCase
One case registered on a `match` builder: a handler with a predicate or schema.
type MatchCase = {
handler: (value: any) => any
predicate?: (value: any) => boolean
schema?: StandardSchemaV1
}MatchBuilder
The fluent builder returned by `match`, tracking input, remaining and output types.
interface MatchBuilder<Input, Remaining, Output> {
with<S extends StandardSchemaV1, R>(
schema: S,
handler: (value: StandardSchemaV1.InferOutput<S>) => R,
): MatchBuilder<Input, Exclude<Remaining, StandardSchemaV1.InferInput<S>>, Output | R>
when(predicate, handler): MatchBuilder<Input, Remaining, Output | ...>
otherwise<R>(handler: (value: Remaining) => R): Output | R
exhaustive: [Remaining] extends [never] ? () => Output : Result.Failure<Remaining>
run(): Output | null
}Each with/when narrows Remaining, and exhaustive is callable only once Remaining is never — otherwise its type surfaces the uncovered cases as a Result.Failure.
Pipe
The overloaded call signature backing `pipe` (1 → 26 functions).
interface Pipe {
<A>(a: A): A
<A, B>(a: A, ab: (a: Awaited<A>) => B): B
<A, B, C>(a: A, ab: (a: Awaited<A>) => B, bc: (b: Awaited<B>) => C): C
// …overloads up to 26 functions
}Every step receives the Awaited result of the previous one, so promises are threaded transparently.
StandardSchemaV1
The vendor-neutral Standard Schema interface used for validation interop.
interface StandardSchemaV1<Input = unknown, Output = Input> {
readonly '~standard': StandardSchemaV1.Props<Input, Output>
}The StandardSchemaV1 namespace also exposes:
- •
Props— the~standardpayload, includingvalidate(value, options?). - •
ValidationResult/SuccessResult/FailureResult— the validate outcome. - •
Issue/PathSegment— the failure issue shape (message + path). - •
Options,Types,InferInput,InferOutput— options and inference helpers.
It extends StandardTypedV1, the shared base carrying version, vendor and inferred types.
StandardTypedV1
The base of the Standard Schema family: version, vendor and inferred input/output types.
interface StandardTypedV1<Input = unknown, Output = Input> {
readonly '~standard': StandardTypedV1.Props<Input, Output>
}The StandardTypedV1 namespace exposes Props (version, vendor, optional types), Types (input/output), and the InferInput/InferOutput helpers reused by the schema variants.
StandardJSONSchemaV1
A Standard-typed schema that can additionally emit JSON Schema for its input/output.
interface StandardJSONSchemaV1<Input = unknown, Output = Input> {
readonly '~standard': StandardJSONSchemaV1.Props<Input, Output>
}Extends the Standard typed base with a jsonSchema converter (input/output) targeting a JSON Schema Target (draft-2020-12, draft-07, openapi-3.0, …). The namespace also exposes Props, Converter, Options, Types, InferInput and InferOutput.