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: