API reference › @evolu/common › Type › unique

function unique<ParentType extends AnyType>(
  parent: UniqueParent<ParentType>,
): BrandType<ParentType, "Unique", UniqueError>;

Defined in: packages/common/src/Type.ts:13418

Array Brand whose items are all different.

Items must be Data, as checked by IsData, so interfaces of Data are accepted. Items are compared with eqData. Primitives use Object.is, so NaN equals NaN while 0 and -0 are different. Objects are compared by structure, so { a: 1, b: 2 } equals { b: 2, a: 1 } and two Sets with the same items are equal. Strings are compared without Unicode normalization; use normalized items when canonically equivalent text must count as equal.

Validation keeps the array unchanged, including its order, so arrays with the same items in a different order remain different values. Use a set of primitives when order is irrelevant.

Primitive items are checked in linear time. An object item is compared only with earlier items of the same kind and first-level contents, but many objects that differ only in nested values are compared pairwise. Bound untrusted arrays with maxLength.

Example

import {
  assertEqual,
  assertErr,
  assertOk,
  array,
  maxLength,
  Number,
  object,
  String,
  unique,
} from "@evolu/common";

const Tags = unique(maxLength(100)(array(String)));

assertOk(Tags.fromUnknown(["local-first", "offline"]), [
  "local-first",
  "offline",
]);

const invalid = Tags.fromUnknown(["a", "b", "a"]);
assertErr(invalid, {
  type: "Unique",
  value: ["a", "b", "a"],
  index: 2,
  previousIndex: 0,
});
assertEqual(
  Tags.formatError(invalid.error),
  'The value ["a","b","a"] has equal items at indexes 0 and 2.',
);

const Points = unique(array(object({ x: Number, y: Number })));

assertErr(
  Points.fromUnknown([
    { x: 1, y: 2 },
    { y: 2, x: 1 },
  ]),
);