Skip to main content

Overview

The constant() decoder accepts only a specific literal value and rejects everything else. It’s useful for validating exact matches against strings, numbers, booleans, null, undefined, or symbols.

Basic Usage

import { constant } from 'decoders';

const statusDecoder = constant('active');

const result = statusDecoder.verify('active');
// Type: 'active'
// Result: 'active'

statusDecoder.verify('inactive'); // Error: Must be "active"
statusDecoder.verify('ACTIVE'); // Error: Must be "active"

Type Signature

function constant<C extends Scalar>(value: C): Decoder<C>;
Where Scalar is string | number | boolean | null | undefined | symbol.

Parameters

value
Scalar
required
The exact value that must be matched. Can be a string, number, boolean, null, undefined, or symbol.

Return Value

Returns a Decoder<C> that only accepts the exact specified value.

Examples

String literals

import { constant } from 'decoders';

const apiVersionDecoder = constant('v2');

const version = apiVersionDecoder.verify('v2');
// Type: 'v2'

Number literals

import { constant } from 'decoders';

const magicNumberDecoder = constant(42);

const result = magicNumberDecoder.verify(42);
// Type: 42

magicNumberDecoder.verify(43); // Error: Must be 42

Boolean literals

import { constant } from 'decoders';

const trueDecoder = constant(true);

const result = trueDecoder.verify(true);
// Type: true

trueDecoder.verify(false); // Error: Must be true

Null and undefined

import { constant } from 'decoders';

// Validate null
const nullDecoder = constant(null);
nullDecoder.verify(null); // OK
nullDecoder.verify(undefined); // Error

// Validate undefined
const undefinedDecoder = constant(undefined);
undefinedDecoder.verify(undefined); // OK
undefinedDecoder.verify(null); // Error
The library provides null_ and undefined_ as pre-built decoders for these common cases:
import { null_, undefined_ } from 'decoders';

null_.verify(null); // OK
undefined_.verify(undefined); // OK

In discriminated unions

import { constant, object, string, number, either } from 'decoders';

const successDecoder = object({
  status: constant('success'),
  data: string,
});

const errorDecoder = object({
  status: constant('error'),
  code: number,
});

const responseDecoder = either(successDecoder, errorDecoder);

const response = responseDecoder.verify({
  status: 'success',
  data: 'Hello',
});
// Type: { status: 'success'; data: string } | { status: 'error'; code: number }

With oneOf for multiple constants

import { constant, oneOf } from 'decoders';

// Instead of multiple constant decoders with either:
const statusDecoder = oneOf([
  constant('draft'),
  constant('published'),
  constant('archived'),
]);

// More concise: use oneOf with string array directly
const statusDecoder2 = oneOf(['draft', 'published', 'archived']);

const status = statusDecoder.verify('published');
// Type: 'draft' | 'published' | 'archived'

Error Messages

The constant() decoder provides clear error messages when validation fails:
import { constant } from 'decoders';

const decoder = constant('expected');

try {
  decoder.verify('actual');
} catch (error) {
  console.error(error.message);
  // Must be "expected"
}
For symbols, the error message uses String() conversion:
const sym = Symbol('mySymbol');
const decoder = constant(sym);

try {
  decoder.verify(Symbol('other'));
} catch (error) {
  console.error(error.message);
  // Must be Symbol(mySymbol)
}

Type Inference

TypeScript correctly infers literal types from constant() decoders:
import { constant } from 'decoders';

const decoder = constant('hello');
type InferredType = ReturnType<typeof decoder.verify>;
// Type: 'hello' (not string)
  • always - Ignores input and always returns a specific value
  • oneOf - Accepts one of several constant values
  • boolean - Accepts any boolean (true or false)
  • string - Accepts any string value

See Also

Build docs developers (and LLMs) love