Skip to content

Releases: gvergnaud/ts-pattern

v3.3.4

20 Dec 10:35
Compare
Choose a tag to compare

Bug fixes

This release fixes a type inference bug specific to Error sub classes. See the related issue for more details: #63

v3.3.2

23 Sep 20:26
Compare
Choose a tag to compare

This patch contains some compile time perf improvements.

@ahejlsberg recently implemented tail call elimination for recursive conditional types (microsoft/TypeScript#45711). This release is preparation work to take advantage of this new feature by making most type helper functions tail recursive. From the non scientific tests I made on my machine, this also improves the compilation time of the tests/ folder quite significantly on our current TS version (4.4). Compilation is ~ 20% faster.

v3.3.1

17 Sep 17:03
Compare
Choose a tag to compare

Features

Add a __.NaN pattern, matching only NaNs values. Thanks @mhintz for adding this

const res = match<number | null>(NaN)
      .with(null, () => 'null!')
      .with(__.NaN, () => 'NaN!')
      .with(__.number, (x) => 'a number!')
      .exhaustive();

console.log(res)
// => 'NaN!'

Bugfix

Update the __.number pattern to also match on NaN values.

Since NaN has type number in TypeScript, there is no way to distinguish a NaN from a regular number at the type level. This was causing an issue where .exhaustive() considered all numbers handled by the __.number pattern even though NaN wasn't matched by it, resulting in possible runtime errors.

const res = match<number | null>(NaN)
      .with(null, () => 'null!')
      .with(__.number, (x) => 'a number!')
      // This used to throw at runtime because NaN wasn't matched by __.number
      .exhaustive();

console.log(res)
// => 'a number!'

v3.2.5

21 Aug 10:30
Compare
Choose a tag to compare

Bugfixes

  • Fix a bug with exhaustiveness checking, where a case could wrongfully be considered handled even if the pattern was containing additional keys that aren't present in the input type. This can happen when making a typo when declaring your pattern for instance, as demonstrated in the issue #44 .
type Person = {
  sex: "Male" | "Female";
  age: "Adult" | "Child";
};

function summary(person: Person): string {
  return (
    match(person)
      // Typo – "agf" should be "age"
      .with({ sex: "Female", agf: "Adult" }, () => "Woman")
      .with({ sex: "Female", age: "Child" }, () => "Girl")
      .with({ sex: "Male", age: "Adult" }, () => "Man")
      .with({ sex: "Male", age: "Child" }, () => "Boy")
      // Bugfix: This pattern is no longer considered exhaustive!
      .exhaustive()
  );
}

v3.2.4

01 Aug 12:28
Compare
Choose a tag to compare

Improvements

  • .otherwise now passes the input value to the handler function. This can be useful when your default handler is a statically defined function and you want to avoid writing an intermediary anonymous function passing the input to it. PR #37 from @oguimbal 🙏

Bug fix

  • It's now possible to pattern-match on native Error objects. To save some compilation time, deep pattern matching on builtin objects is disabled, but it turns out this can be pretty handy to pattern match on native Error objects because some libs (like @apollo/client) enhance them with additional properties.

v3.2.2

21 Jul 13:28
Compare
Choose a tag to compare

Fix a bug reported in issue #40, where object pattern containing a single wildcard would match any object, even if the key used by the pattern wasn't present on the input object.

type Id = { teamId: number } | { storeId: number };

const selectedId: Id = { teamId: 1 };

match<Id>(selectedId)
  .with({ storeId: __ }, () => "storeId")
  .with({ teamId: __ }, () => "teamId")
  .exhaustive()
// Now outputs "teamId" instead of "storeId"

v3.2.1

01 Jul 20:25
Compare
Choose a tag to compare

This minor release adds 3 new features to the lib.

__.nullish

A new wildcard pattern, matching null | undefined. Thanks a lot @m-rutter for implementing this and fixing some issues with pattern inference along the way! 🎉

import { match, __ } from 'ts-pattern';
const input = null;
const output = match<number | string | boolean | null | undefined>(input)
  .with(__.string, () => 'it is a string!')
  .with(__.number, () => 'it is a number!')
  .with(__.boolean, () => 'it is a boolean!')
  .with(__.nullish, () => 'it is either null or undefined!')
  .with(null, () => 'it is null!')
  .with(undefined, () => 'it is undefined!')
  .run();
console.log(output);
// => 'it is either null or undefined!'

instanceOf

A new function creating a pattern, checking if a value is an instance of a particular class. This feature was requests in #24, it was possible implement it in userland using a when pattern, but the types were a bit tricky so I thought it made sense to add first class support for this.

import { match, instanceOf } from 'ts-pattern';

class A {
  a = 'a';
}
class B {
  b = 'b';
}

const output = match<{ value: A | B }>({ value: new A() })
  .with({ value: instanceOf(A) }, (a) => 'instance of A!')
  .with({ value: instanceOf(B) }, (b) => 'instance of B!')
  .exhaustive();

console.log(output);
// => 'instance of A!'

isMatching

A helper function to create a type guard function from a pattern. This can be really useful when making a runtime type assertion, for instance if you want to check that an API response matches what you are expecting.

import { isMatching, __ } from 'ts-pattern';

const isBlogPost = isMatching({
  title: __.string,
  content: __.string,
});

const res: unknown = await fetch(...)
                                
if (isBlogPost(res)) {
  // res: { title: string, content: string }
}

v3.1.5

12 May 09:03
Compare
Choose a tag to compare

This release features an important performance improvement: ts-pattern now checks if the pattern matches and performs selections coming from select() patterns all in one pass.

The performance difference won't be very significant in most use cases, but it could be noticable when frequently pattern matching using deep patterns.

v3.1.4

10 May 12:55
Compare
Choose a tag to compare

Bug Fixes:

  • Type inference improvement when combining a when(predicate) pattern with a not() pattern.

Performance improvements:

  • Reduce the number of if statements required to see if an object pattern matches the input
  • Remove an unnecessary loop on list pattern matching

v3.1.2

06 Apr 09:20
3149bf3
Compare
Choose a tag to compare

Some compile-time performance improvement on the ExtractPreciseValue type, inferring the type matched by a given pattern.