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