ts-pattern icon indicating copy to clipboard operation
ts-pattern copied to clipboard

[Question] What are the benefit of using ts-pattern in this examples?

Open shinokada opened this issue 3 years ago • 1 comments

(I apologize in advance for asking a question in the enhancement section.)

I'm new to ts-pattern and I'd like to know the benefits of using it. I created two examples without ts-pattern and with ts-pattern. The following code may not be good enough but this is what I can do for now. Both examples achieve the same and ts-pattern needs more lines. So I'm wondering what the benefit of using ts-pattern. (I will be grateful if you can point out what I can do better in the following code.)

Ex1, without ts-pattern: REPL

// shape types
type Shape = Triangle | Circle;

type Triangle = {
  type: 'Triangle';
  base: number;
  height: number;
};

type Circle = {
  type: 'Circle';
  radius: number;
};

const shape1: Triangle = {
  type: 'Triangle',
  base: 5,
  height: 6,
};

const shape2: Circle = { type: 'Circle', radius: 10 };

const area = (shape: Shape): string => {
  switch (shape.type) {
    case 'Triangle':
      return `Area is ${(shape.base * shape.height) / 2}`;

    case 'Circle':
      return `Area equals ${(shape.radius * shape.radius * Math.PI).toFixed(
        1
      )}`;
  }
};

console.log(area(shape1));
console.log(area(shape2));

Ex2 with ts-pattern: REPL

import { match  } from 'ts-pattern';

type Data =
  | { type: 'triangle'; base: number; height: number }
  | { type: 'circle'; radius: number };

type Shape = { type: 'geometry'; data: Data } | { type: 'error'; error: Error };

const triangle: Shape = {
  type: 'geometry',
  data: { type: 'triangle', base: 5, height: 6 },
};

const circle: Shape = {
  type: 'geometry',
  data: { type: 'circle', radius: 10 },
};

const findarea = (shape: Shape) => {
  return match(shape)
    .with(
      { type: 'error' },
      (err) => `<p>Oups! An error occured</p>, ${err.error}`
    )
    .with(
      { type: 'geometry', data: { type: 'triangle' } },
      (res) => `${(res.data.base * res.data.height) / 2}`
    )
    .with(
      { type: 'geometry', data: { type: 'circle' } },
      (res) => `${res.data.radius * res.data.radius * Math.PI}`
    )
    .exhaustive();
};

console.log(findarea(triangle));
console.log(findarea(circle));

shinokada avatar Jun 13 '22 11:06 shinokada

Maybe it would be more meaningful comparing how to handle the exact same data structures. But, anyways, with ts-pattern (and the ending .exhaustive() clause at the end) you've got the guarantee at compile time that all cases are handle (which is not the case with the switch statement).

err0r500 avatar Jun 15 '22 15:06 err0r500