gvergnaud / ts-pattern

🎨 The exhaustive Pattern Matching library for TypeScript, with smart type inference.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Matching a String Literal from an Array

arb opened this issue · comments

I'm using version version 4.0.0 of ts-pattern. I would like to write a pattern match that works like this:

const first = ['one', 'two', 'three', 'four'];
const second = ['nine', 'ten'];
const input = 'three';

match(input)
.with(...first, () => 'input is part of the first array')
.with(...second, () => 'input is part of the second array');
.otherwise(() => 'input is not part of either array');

with doesn't seem like it wants to be called via a spread. I've come up with a workaround of using P.when and first.includes and second.includes but that seems like a hack. Does anyone have a suggestion on how to accomplish this?

Hey,

Spreading should work when your arrays are defined with as const, to make TypeScript infer than as tuples instead of arrays:

const first = ['one', 'two', 'three', 'four'] as const;
const second = ['nine', 'ten'] as const;
const input = 'three' as string;

match(input)
.with(...first, () => 'input is part of the first array')
.with(...second, () => 'input is part of the second array')
.otherwise(() => 'input is not part of either array');

You could also use P.union for this:

const first = ['one', 'two', 'three', 'four'] as const;
const second = ['nine', 'ten'] as const;
const input = 'three' as string;

match(input)
.with(P.union(...first), () => 'input is part of the first array')
.with(P.union(...second), () => 'input is part of the second array')
.otherwise(() => 'input is not part of either array');

Regular arrays aren't permitted because their type isn't precise enough to get the kind of type inference TS-Pattern aims to provide. Only tuple types are supported as patterns.

OF COURSE! Thank you @gvergnaud!