Blog
ts-pattern usage in Documenso source code

ts-pattern usage in Documenso source code

In this article, we analyse the ts-pattern usage in Documenso source code, but before that, let’s learn what a ts-pattern library is.

ts-pattern

ts-pattern is an exhaustive Pattern Matching library for TypeScript with smart type inference. Write better and safer conditions. Pattern matching lets you express complex conditions in a single, compact expression. Your code becomes shorter and more readable. Exhaustiveness checking ensures you haven’t forgotten any possible case.

import { match, P } from 'ts-pattern';
type Data =
 | { type: 'text'; content: string }
 | { type: 'img'; src: string };
type Result =
 | { type: 'ok'; data: Data }
 | { type: 'error'; error: Error };
const result: Result = …;
const html = match(result)
 .with({ type: 'error' }, () => <p>Oups! An error occured</p>)
 .with({ type: 'ok', data: { type: 'text' } }, (res) => <p>{res.data.content}</p>)
 .with({ type: 'ok', data: { type: 'img', src: P.select() } }, (src) => <img src={src} />)
 .exhaustive();

This example is pretty self-explanatory. Now that we understand a basic example of how ts-pattern works. Let’s apply this to the code found in Documenso.

match usage in Documenso source code.

In Documenso source code, there is a file named upload/put-file.ts and you will find this below code at line 48.

import { match } from 'ts-pattern';
import { env } from 'next-runtime-env';
export const putFile = async (file: File) => {
 const NEXT_PUBLIC_UPLOAD_TRANSPORT = env('NEXT_PUBLIC_UPLOAD_TRANSPORT');
return await match(NEXT_PUBLIC_UPLOAD_TRANSPORT)
 .with('s3', async () => putFileInS3(file))
 .otherwise(async () => putFileInDatabase(file));
};

match is applied against a variable named NEXT_PUBLIC_UPLOAD_TRANSPORT. Based on the example above, you 
pass a parameter to match and run a check against it using with. In the example from documentation above, it was based on type and data, but here in this code snippet from Documenso, it is a different story.

with is checked against a string — ‘s3’. At this point, I just wanted to find out what is expected as value for the variable Next_PUBLIC_UPLOAD_TRANSPORT. I searched for this variable — NEXT_PUBLIC_UPLOAD_TRANSPORT across the codebase and found its type definition in a file named process-env.d.ts. This file is in package named tsconfig. Documenso is a monorepo and contains workspaces inside apps folder and packages inside packages folder.

NEXT_PUBLIC_UPLOAD_TRANSPORT?: 'database' | 's3';

NEXT_PUBLIC_UPLOAD_TRANSPORT accepts only two string literals — ‘database’ or ‘s3’. Now it makes sense, you see. This is why you have a check against ‘s3’ string to call a function named putFileInS3.

.with('s3', async () => putFileInS3(file))

Otherwise, the value in NEXT_PUBLIC_UPLOAD_TRANSPORT will be ‘database’ and it handled using otherwise:

.otherwise(async () => putFileInDatabase(file));

This reminds me of the .exhaustive() function. ts-pattern documentation says this about exhaustive function — 

Exhaustiveness checking ensures you haven’t forgotten any possible case.

I think using .exhaustive() when you are dealing with a match against an object, like the one provided in documentation example, makes sense. Since this variable NEXT_PUBLIC_UPLOAD_TRANSPORT accepts only two string literals — ‘database’ or ‘s3’, there’s only string and no object to match against, that’s why there is no need for using .exhaustive(), instead .otherwise is used.

About me:

Hey, my name is Ramu Narasinga. I study large open-source projects and create content about their codebase architecture and best practices, sharing it through articles, videos.

I am open to work on interesting projects. Send me an email at ramu.narasinga@gmail.com

My Github — https://github.com/ramu-narasinga

My website — https://ramunarasinga.com

My Youtube channel — https://www.youtube.com/@thinkthroo

Learning platform — https://thinkthroo.com

Codebase Architecture — https://app.thinkthroo.com/architecture

Best practices — https://app.thinkthroo.com/best-practices

Production-grade projects — https://app.thinkthroo.com/production-grade-projects

References:

  1. https://github.com/documenso/documenso/blob/main/packages/lib/universal/upload/put-file.ts#L51

  2. https://www.npmjs.com/package/ts-pattern

  3. https://github.com/documenso/documenso/blob/main/packages/tsconfig/process-env.d.ts#L25

We use cookies
We use cookies to ensure you get the best experience on our website. For more information on how we use cookies, please see our cookie policy.

By clicking "Accept", you agree to our use of cookies.

Learn more