Skip to content

@cqrs-ddd/untyped

A typed replacement for as any when code must read a property the type does not declare, such as framework metadata on a wrapper object. untyped(value) returns the same value typed as T & Record<string | symbol, unknown>: declared properties keep their types, and every other property reads as unknown, so the caller must narrow it. It satisfies Biome’s noExplicitAny without suppressing the rule.

Terminal window
npm install @cqrs-ddd/untyped
# or
pnpm add @cqrs-ddd/untyped

Requires Node.js 22.12 or later. No dependencies, no framework.

Published as an ES module; a CommonJS application loads it with require(). Coming from 0.3.x, see Upgrading from 0.3.x.

import { untyped } from '@cqrs-ddd/untyped';
const scope = untyped(wrapper).scope; // unknown: narrow it before use
if (typeof scope === 'number') {
// ...
}
Export Signature Description
untyped <T>(value: T) => T & Record<string | symbol, unknown> The same value, with undeclared properties typed unknown

It changes only the type; the value is returned as is.

Read a symbol-keyed property that a library sets on an object it hands you:

import { untyped } from '@cqrs-ddd/untyped';
const TRACE = Symbol.for('app.trace');
function traceOf(request: object): string | undefined {
const trace = untyped(request)[TRACE];
return typeof trace === 'string' ? trace : undefined;
}

Declared properties keep their types, so only the undeclared read needs narrowing:

import { untyped } from '@cqrs-ddd/untyped';
interface Command {
readonly id: string;
}
function describe(command: Command): string {
const view = untyped(command);
const source = view.source; // unknown
return typeof source === 'string' ? `${view.id} from ${source}` : view.id; // view.id is string
}

Migrating from @nestjs-pipeline/core 0.1.x

Section titled “Migrating from @nestjs-pipeline/core 0.1.x”

untyped was exported by @nestjs-pipeline/core 0.1.x and is no longer exported there in 0.2.0.

// Before (0.1.x)
import { untyped } from '@nestjs-pipeline/core';
// After (0.2.0)
import { untyped } from '@cqrs-ddd/untyped';

The signature is unchanged. Add @cqrs-ddd/untyped to your own dependencies.

Dual-licensed under AGPLv3 and a Commercial License. See the root LICENSE and COMMERCIAL_LICENSE.txt for details.