Kensio Software Blog »

@kensio/smartass 1.15.0 improves overlap-preserving type refinement

Hugh Grigg | Kensio Software | Monday 15 Jun 2026

Version v1.15.0 of the @kensio/smartass package improves type refinement for assertion functions and composable matchers.

The goal is to incorporate existing type information from the calling scope when possible, rather than widening values to a less precise asserted type.

For example, consider a value whose type is already known to be:

import { assertObjectMatches, typeString } from "@kensio/smartass";

interface Foo {
  bar?: {
    foobar?: "hello" | "world" | 123 | null;
  };
}

function getFoo(): Foo {
  return { bar: { foobar: "hello" } };
}

const foo = getFoo();

assertObjectMatches(foo, {
  bar: { foobar: typeString() },
});

foo.bar.foobar;
// "hello" | "world"

The typeString() composable matcher works from within assertObjectMatches() to provide type refinement back to the calling scope. TypeScript can combine this type assertion with the existing type information in the calling scope to precisely narrow the type of foo.bar.foobar to the literal union type "hello" | "world";

Prior to this improvement, it would have been easy for an assertion signature to broaden the type to just string.

Version v1.15.0 updates all the assertion signatures and composable matchers in the package to provide this overlap-preserving type refinement.

This tends to be helpful in tests, because it combines runtime validation with precise compile-time type checking. After an assertion succeeds, TypeScript can often infer more specific types than before, which reduces the need for manual casts and helps IDE autocomplete provide more accurate suggestions.

npm:

https://www.npmjs.com/package/@kensio/smartass

GitHub:

https://github.com/KensioSoftware/smartass