Object with `any` breaks `.with` chaining
gabrielalmeida opened this issue · 4 comments
Describe the bug
Codegen generates type defs that includes any
as object property types.
ts-pattern
.with
chaining breaks when trying to match against those objects.
// Sample type generated via codegen
type Rule = {
// Replace any with other types and it works as expected
unit: any;
};
const sample_rule: Rule = {
unit: "day",
};
const result = match(sample_rule)
.with({ unit: "day" }, () => "x")
// Type is broken when chaining second .with, comment line below and it works as expected
.with({ unit: "hour" }, () => "y")
.otherwise(() => "w");
TSError: ⨯ Unable to compile TypeScript:
src/index.ts:16:11 - error TS2345: Argument of type '{ unit: string; }' is not assignable to parameter of type 'PatternMatcher<never>'.
Object literal may only specify known properties, and 'unit' does not exist in type 'Matcher<never, unknown, any, any, unknown>'.
Code Sandbox with a minimal reproduction case
https://codesandbox.io/p/sandbox/misty-bird-wsckjn
Versions
- TypeScript version: 5.2.2
- ts-pattern version: 5.0.5
- environment: node v16.17.0
v4.1.2
introduced "Make subsequent .with clause inherit narrowing from previous clauses" which seems to be the cause of this behavior. Reverting to a version prior than that works as expected.
That's unfortunately coming from this weird TypeScript behavior:
type X = Exclude<{ unit: any }, { readonly unit: 'day' }>;
// ^? never
I would expect X
to be { unit: any }
here, because { readonly unit: 'day' }
is a small subset of { unit: any }
...
I don't know if there is a fix for this that would be satisfactory in terms of type-checking performance (for example that wouldn't require walking through the input types to find anys and turn them into unknowns).
Is there a workaround or a solution for this?
Use unknown
instead of any