question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Add support for pattern matching class instances

See original GitHub issue

Let’s suppose we have the following types:

class UserId {
    constructor(public val: string, private _?: string) {}
}

class SellerId {
    constructor(public val: string, private _?: string) {}
}

type Ids = UserId | SellerId

I’ve found that for nominal typing, a class with a private property is IMO the best and simplest way to achieve it. It is quite an advantage having both constructor and type on the same place. No unique symbol branding and no type casting on the constructor functions.

Also, as long as no inheritance shenanigans happen it allows to do strict pattern matching out of the box:


const assertNever = (val: never): never => {
    throw new Error('Should never happen')
}

const processId = (id: Ids): string => {

    if (id instanceof UserId) {
        return 'this is a user id'
    } else if (id instanceof SellerId) {
        return 'this is a seller id'
    }

    return assertNever(id)
}

Sadly, I have to put an ugly assertNever at the end.

I just discovered this lib, and it would be quite nice to be able to pattern match those cases too without tedious instanceof chains.

A sample implementation would be something like:

match(id)
    .with(UserId, (res) => 'UserId detected')
    .with(SellerId, (res) => 'SellerId detected')
    .exhaustive()

How difficult would it be to implement it?

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

3reactions
gvergnaudcommented, Mar 23, 2021

Having an instanceOf() pattern for this use case would be an interesting idea (if it wasn’t a reserved word). I’ll think about adding it to the lib.

in the meantime using when + an isInstanceOf helper function to create the predicate should work:

class UserId {
  constructor(public val: string, private _?: string) {}
}

class SellerId {
  constructor(public val: string, private _?: string) {}
}

type Ids = UserId | SellerId;

// Helper function
type AnyConstructor = new (...args: any[]) => any;

function isInstanceOf<T extends AnyConstructor>(classConstructor: T) {
  return (val: unknown): val is InstanceType<T> => val instanceof classConstructor;
}

const id = new UserId("") as Ids;

// This works fine
const result = match<Ids>(id)
  .when(isInstanceOf(UserId), (x) => console.log("user id"))
  .when(isInstanceOf(SellerId), (y) => console.log("seller id"))
  .exhaustive();

your matchClass function wasn’t working because val is T states that val is the constructor, not an instance of this class. you need to use val is InstanceType<T> instead.

0reactions
gvergnaudcommented, Jul 1, 2021

an instanceOf pattern has been added in the latest release! https://github.com/gvergnaud/ts-pattern/releases/tag/v3.2.1

Read more comments on GitHub >

github_iconTop Results From Across the Web

Structural pattern matching tutorial | Pydon't - Mathspp
Structural pattern matching is coming in Python 3.10 and this article explores how to use it to write Pythonic code, showing the best...
Read more >
Pattern Matching | Tour of Scala - Scala Documentation
Pattern matching is a mechanism for checking a value against a pattern. A successful match can also deconstruct a value into its constituent...
Read more >
Case Classes and Pattern Matching - Artima
This chapter introduces case classes and pattern matching, twin constructs that support you when writing regular, non-encapsulated data ...
Read more >
Pattern matching overview - C# guide | Microsoft Learn
C# pattern matching provides more concise syntax for testing expressions and taking action when an expression matches. The " is expression" ...
Read more >
Pattern matching | PyCharm Documentation - JetBrains
Patterns consist of sequences, mappings, primitive data types, and class instances. Pattern matching allows extracting information from complex data types, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found