object-shape-tester
Version:
Test object properties and value types.
55 lines (54 loc) • 1.72 kB
JavaScript
import { check } from '@augment-vir/assert';
import { wrapString } from '@augment-vir/common';
import { Kind, Type, TypeRegistry } from '@sinclair/typebox';
import { registerErrorMessage } from '../errors/error-message.js';
import { defineShape } from '../shape/shape.js';
/**
* Creates a shape that requires matching the exact value give.
*
* @category Shape
* @example
*
* ```ts
* import {exactShape, checkValidShape} from 'object-shape-tester';
*
* const myShape = exactShape('a');
*
* checkValidShape('a', myShape); // `true`
* checkValidShape('c', myShape); // `false`
*
* // normally passing a string to a shape will simplify the shape.
* checkValidShape('c', defineShape('a')); // `true`
* ```
*/
export function exactShape(value) {
if (check.isSymbol(value)) {
return exactSymbolShape(value);
}
return defineShape(Type.Const(value, { default: value }));
}
/**
* Kind for {@link exactShape}'s type registry entry when the value given to {@link exactShape} is a
* symbol.
*
* @category Internal
*/
export const exactSymbolKind = 'ExactSymbol';
function exactSymbolShape(value) {
if (!TypeRegistry.Has(exactSymbolKind)) {
TypeRegistry.Set(exactSymbolKind, (schema, value) => {
return value === schema.symbol;
});
}
registerErrorMessage(exactSymbolKind, ({ schema }) => {
const symbolDescription = schema.symbol?.description
? wrapString({ value: schema.symbol.description, wrapper: "'" })
: '<unnamed symbol>';
return `Expected symbol ${symbolDescription}`;
});
return defineShape(Type.Unsafe({
[Kind]: exactSymbolKind,
symbol: value,
default: value,
}));
}