gvergnaud/ts-pattern

Does not seem to resolve discriminated unions correctly

ian-schu opened this issue ยท 4 comments

Describe the bug
Love this library and have enjoyed adopting it across our codebase ๐Ÿ‘๐Ÿป

Today I'm trying to use ts-pattern to handle a discriminated union type, and within each with statement it looks like the type is NOT resolved correctly. I played with this a few different ways, and found that a native switch statement does exactly what I want, but ts-pattern does not.

Hopefully this is just user error, maybe I'm getting something subtly wrong with the match API.

Code Sandbox with a minimal reproduction case
Once the language server finishes loading on this example, you'll see compiler warnings on the ts-pattern attempt at this problem, whereas the native switch version has no problems.

https://codesandbox.io/p/sandbox/ts-pattern-discriminated-union-psqjrl?file=%2Fsrc%2Findex.ts%3A63%2C3

Versions

  • TypeScript version: 5.3.3, also observed with latest
  • ts-pattern version: 4.3.0, also observed with 5.1.0
  • environment: node v20.11.0

you should use narrowed instances to benefit from pattern matching.

match(object)
    .with({type:"variant1"}, (object) => {
      console.log(object.data.someField);
      console.log(object.flavor);
    })
    .with({type:"variant2"}, (object) => {
      console.log(object.data.length);
      console.log(object.kind);
    })
    .exhaustive();
};

Yes, as @JUSTIVE showed, you need to match on the whole object and use the narrowed reference that's provided as a parameter to handler functions.

I wish there was a way to narrow an object that's in scope based on the pattern given to .with, but it isn't possible today.

maybe there's some point where we could benefit from typescript 5.5's type predicate inference. not sure how we'll benefit from it, but since it automatically narrows type, I'm pretty sure there's some way.

Thanks guys! I had no idea I was supposed to be matching on the whole object. It's interesting that the native TS switch will do this exactly as I hoped ๐Ÿค”

Anyway, I am unblocked on this ๐Ÿ‘๐Ÿป

Really interested in the TS 5.5 predicate inference. Seems like that would allow match() to behave a lot more like the native switch that I gave in my sandbox.