API reference › @evolu/common › Type › DiscriminatedUnionType
Defined in: packages/common/src/Type.ts:12471
The routed Type returned by discriminatedUnion.
Extends
Type<"DiscriminatedUnion",DiscriminatedUnionInput<Key,Members>,Members[number]["Output"],DiscriminatedUnionNodeError<Key,Members>,DiscriminatedUnionInputType<DiscriminatedUnionInput<Key,Members>,DiscriminatedUnionParentError<Key,Members>>,DiscriminatedUnionCompleteError<Key,Members>,never,CanonicalInputSubset<DiscriminatedUnionInput<Key,Members>,CanonicalInputOf<Members[number]>>,AllTypesUseIdentityEncoding<Members[number]>>
Properties
[concreteTypeSymbol]
readonly [concreteTypeSymbol]: true;
Defined in: packages/common/src/Type.ts:580
Inherited from
[customFromSymbol]
readonly [customFromSymbol]: never;
Defined in: packages/common/src/Type.ts:584
Inherited from
[errorsSymbol]
readonly [errorsSymbol]: DiscriminatedUnionCompleteError;
Defined in: packages/common/src/Type.ts:576
Inherited from
[identityEncodingSymbol]
readonly [identityEncodingSymbol]: AllTypesUseIdentityEncoding;
Defined in: packages/common/src/Type.ts:587
Inherited from
[reflectedTypesSymbol]?
readonly optional [reflectedTypesSymbol]?: Members[number];
Defined in: packages/common/src/Type.ts:12491
~standard
readonly ~standard: Props<DiscriminatedUnionMemberInput<Key, Members[number]>, Members[number]["Output"]>;
Defined in: packages/common/src/Type.ts:527
Standard Schema V1 interoperability.
Validation runs the complete fromUnknown pipeline synchronously and
reports every structured failure as a localized message with a separate
property path.
Inherited from
CanonicalInput
CanonicalInput: CanonicalInputSubset<
DiscriminatedUnionMemberInput<Key, Members[number]>,
CanonicalInputOf<Members[number]>
>;
Defined in: packages/common/src/Type.ts:512
The statically known subtype of Input returned by the complete to
operation.
Compared with Input, CanonicalInput can exclude invalid candidates and alternative representations that encoding cannot emit. It can remain wider than the values actually emitted when a refinement follows an arbitrary transformation. Structural Types derive it from the CanonicalInput of their contained Types.
This is a type-only phantom property. Use it through typeof Type.CanonicalInput; it does not exist at runtime.
Inherited from
Error
Error: DiscriminatedUnionMemberError<
CorrelatedDiscriminatedUnionNodeIssueFor<Key, Members[number]>
>;
Defined in: packages/common/src/Type.ts:506
The error introduced at this Type node.
This is a type-only phantom property. Use it through typeof Type.Error;
it does not exist at runtime.
Inherited from
formatError
readonly formatError: TypeErrorFormatter<DiscriminatedUnionCompleteError<Key, Members>>;
Defined in: packages/common/src/Type.ts:646
Formats an error returned by fromUnknown or from as one human-readable
message. Predefined Types use English; localizeTypes derives Types
with localized formatters.
Structural errors retain nested errors and their locations in the typed error value. This formatter does not encode paths or enumerate nested errors in its message.
Example
import {
assertEqual,
assertType,
Data,
assertErr,
String,
} from "@evolu/common";
const result = String.fromUnknown(42);
assertErr(result);
assertType(Data, result.error);
assertEqual(result.error, {
type: "TypeOf",
expected: "String",
value: 42,
});
assertEqual(String.formatError(result.error), "A value 42 is not a string.");
Inherited from
from
readonly from: FromOperation<Members[number]["Output"], DiscriminatedUnionMemberError<CorrelatedDiscriminatedUnionNodeIssueFor<Key, Members[number]>>, DiscriminatedUnionInputType<DiscriminatedUnionMemberInput<Key, Members[number]>, DiscriminatedUnionParentError<Key, Members>>>;
Defined in: packages/common/src/Type.ts:738
Runs the remaining Type pipeline from a typed boundary.
from accepts this Type's Output. Its first .parent accepts the
immediate parent Output, and each additional suffix moves the boundary one
Type toward the root. The deepest suffix accepts the root Output.
Every entry point asserts its selected boundary before running the
remaining pipeline. Assertion failures throw because they indicate a
developer error. The Error message identifies the expected boundary Type,
and its cause preserves the structured validation error. Only failures
introduced after that boundary are returned through Result.
Example
A form already guarantees every constraint on a title, while a new note input guarantees only trimmed text. The note's parent boundary validates only the constraints that the form does not guarantee:
import {
assertOk,
assertType,
flatMapResult,
NonEmptyTrimmedString100,
object,
TrimmedString,
type MaxLengthError,
type MinLengthError,
type Result,
} from "@evolu/common";
const Todo = object({
title: NonEmptyTrimmedString100,
note: NonEmptyTrimmedString100,
});
const saveTodo = (title: NonEmptyTrimmedString100, note: TrimmedString) => {
// @ts-expect-error TrimmedString does not guarantee a non-empty value
// with at most 100 characters.
Todo.from({ title, note });
return flatMapResult(Todo.props.note.from.parent.parent(note), (note) =>
Todo.from({ title, note }),
);
};
const title = NonEmptyTrimmedString100.orThrow("Buy milk");
const note = TrimmedString.orThrow("Remember oat milk");
const result = saveTodo(title, note);
assertType<
Result<typeof Todo.Output, MaxLengthError<100> | MinLengthError<1>>,
typeof result
>();
assertOk(result, { title, note });
Inherited from
fromUnknown
readonly fromUnknown: (value: unknown, options?: ValidationOptions) => Result<Members[number]["Output"], DiscriminatedUnionCompleteError<Key, Members>>;
Defined in: packages/common/src/Type.ts:606
Decodes an unknown value through the complete Type pipeline.
Example
import { assertOk, PositiveInt } from "@evolu/common";
const value: unknown = 42;
const result = PositiveInt.fromUnknown(value);
assertOk(result, 42);
Inherited from
Input
Input: DiscriminatedUnionMemberInput<Key, Members[number]>;
Defined in: packages/common/src/Type.ts:504
The complete typed decoding boundary accepted by orThrow, orNull, and
the deepest available from operation.
Input includes candidates that validation can reject and noncanonical representations that decoding can normalize.
This is a type-only phantom property. Use it through typeof Type.Input;
it does not exist at runtime.
Inherited from
is
readonly is: (value: unknown) => value is Members[number]["Output"];
Defined in: packages/common/src/Type.ts:674
Checks whether an unknown value is a valid semantic Output.
This is an exact Output-membership check, not a test of whether an encoded Input could be decoded. It can be used directly as a TypeScript type guard, including as an Array filter predicate.
Example
import {
assertFalse,
assertType,
assertTrue,
Int64FromInt64String,
type Int64,
} from "@evolu/common";
const values: ReadonlyArray<unknown> = [42n, "42", null];
const integers = values.filter(Int64FromInt64String.is);
assertType<Array<Int64>, typeof integers>();
assertTrue(Int64FromInt64String.is(42n));
assertFalse(Int64FromInt64String.is("42"));
Inherited from
key
readonly key: Key;
Defined in: packages/common/src/Type.ts:12492
members
readonly members: Members;
Defined in: packages/common/src/Type.ts:12493
name
readonly name: "DiscriminatedUnion";
Defined in: packages/common/src/Type.ts:518
The name identifying this Type node.
Inherited from
orNull
readonly orNull: (value: DiscriminatedUnionMemberInput) => Members[number]["Output"] | null;
Defined in: packages/common/src/Type.ts:847
Shorthand for calling getOrNull with the result of the deepest
from operation, which accepts this Type's Input.
The typed Input boundary is asserted before the remaining pipeline runs.
A boundary violation throws a developer error directly; getOrNull maps
only a validation error returned after that boundary to null.
Type.orNull.parent(value) does not exist. To return null after starting
from a typed boundary, call getOrNull with the corresponding from
operation.
Use orNull when absence is the complete meaning of failure and the error
is intentionally irrelevant. Use fromUnknown or a typed from operation
when the caller needs to inspect, format, or otherwise handle the error.
Example
import { assertEqual, getOrNull, minLength, String } from "@evolu/common";
const NonEmptyString = minLength(1)(String);
const value = NonEmptyString.orNull("Evolu");
// Equivalent because `from.parent` is this Type's deepest `from` operation:
const sameValue = getOrNull(NonEmptyString.from.parent("Evolu"));
assertEqual(value, "Evolu");
assertEqual(sameValue, value);
assertEqual(NonEmptyString.orNull(""), null);
Inherited from
orThrow
readonly orThrow: (value: DiscriminatedUnionMemberInput, options?: ValidationOptions) => Members[number]["Output"];
Defined in: packages/common/src/Type.ts:807
Shorthand for calling getOrThrow with the result of the deepest
from operation, which accepts this Type's Input.
The typed Input boundary is asserted before the remaining pipeline runs.
A boundary violation throws a developer error directly; getOrThrow maps
only a validation error returned after that boundary.
Type.orThrow.parent(value) does not exist. To throw after starting from a
typed boundary, call getOrThrow with the corresponding from operation.
Use orThrow for startup and configuration, module constants, test
fixtures, and internal invariants where failure must stop the current flow.
Prefer fromUnknown or a typed from operation for ordinary application
input whose validation failure can be reported or recovered from.
Example
import { assertEqual, getOrThrow, minLength, String } from "@evolu/common";
const NonEmptyString = minLength(1)(String);
const value = NonEmptyString.orThrow("Evolu");
// Equivalent because `from.parent` is this Type's deepest `from` operation:
const sameValue = getOrThrow(NonEmptyString.from.parent("Evolu"));
assertEqual(value, "Evolu");
assertEqual(sameValue, value);
Inherited from
Output
Output: Members[number]["Output"];
Defined in: packages/common/src/Type.ts:505
The semantic value produced by decoding and accepted by bare from and
to.
This is a type-only phantom property. Use it through typeof Type.Output;
it does not exist at runtime.
Inherited from
parent
readonly parent: DiscriminatedUnionInputType;
Defined in: packages/common/src/Type.ts:590
The one preceding Type node, or null for a root Type.
Inherited from
to
readonly to: ToOperation<Members[number]["Output"], CanonicalInputSubset<DiscriminatedUnionMemberInput<Key, Members[number]>, CanonicalInputOf<Members[number]>>, DiscriminatedUnionInputType<DiscriminatedUnionMemberInput<Key, Members[number]>, DiscriminatedUnionParentError<Key, Members>>>;
Defined in: packages/common/src/Type.ts:766
Asserts and encodes an Output toward its canonical Input
representation.
to runs the complete encoding pipeline. Its first .parent stops at the
immediate parent Output, and each additional suffix stops one Type closer
to the root. Every entry point accepts this Type's Output.
Example
import { assertEqual, Int64, Int64FromInt64String } from "@evolu/common";
const value = Int64.orThrow(42n);
assertEqual(Int64FromInt64String.to(value), "42");