Summary
The instance methods .isOk() / .isErr() / .isDefect() return boolean and do not narrow. The standalone isOk(r) / isErr(r) / isDefect(r) functions do narrow. The dual API is a sharp, repeat-bite footgun — especially for codebases migrating from neverthrow, where the methods narrow.
Where
isOk(): boolean;
isErr(): boolean;
isDefect(): boolean;
vs the standalone guards:
declare function isOk<T, E>(r: Result<T, E>): r is OkView<T, E>;
declare function isErr<T, E>(r: Result<T, E>): r is ErrView<E, T>;
declare function isDefect<T, E>(r: Result<T, E>): r is DefectView<T, E>;
Why it matters
The natural, neverthrow-shaped pattern silently fails to compile away the other variants:
if (result.isErr()) {
result.error; // ❌ not narrowed — `.error` not accessible
}
In a downstream consumer this is the single most-repeated mistake (it's documented as a "common mistake" in that repo's agent rules, and a code-review bot flagged a doc example that misused .isErr() as a guard). Anyone coming from neverthrow walks straight into it.
Proposal
Type the methods as type predicates so they narrow on their own:
isOk(): this is OkView<T, E>;
isErr(): this is ErrView<E, T>;
isDefect(): this is DefectView<T, E>;
This collapses the two parallel APIs into one and eliminates a whole class of mistakes. If there's a deliberate reason to keep the methods non-narrowing (e.g. steering users toward exhaustive match), documenting that rationale next to the standalone guards would at least make the split intentional rather than surprising.
Summary
The instance methods
.isOk()/.isErr()/.isDefect()returnbooleanand do not narrow. The standaloneisOk(r)/isErr(r)/isDefect(r)functions do narrow. The dual API is a sharp, repeat-bite footgun — especially for codebases migrating from neverthrow, where the methods narrow.Where
vs the standalone guards:
Why it matters
The natural, neverthrow-shaped pattern silently fails to compile away the other variants:
In a downstream consumer this is the single most-repeated mistake (it's documented as a "common mistake" in that repo's agent rules, and a code-review bot flagged a doc example that misused
.isErr()as a guard). Anyone coming from neverthrow walks straight into it.Proposal
Type the methods as type predicates so they narrow on their own:
This collapses the two parallel APIs into one and eliminates a whole class of mistakes. If there's a deliberate reason to keep the methods non-narrowing (e.g. steering users toward exhaustive
match), documenting that rationale next to the standalone guards would at least make the split intentional rather than surprising.