DEV Community

Ramu Narasinga
Ramu Narasinga

Posted on • Edited on • Originally published at thinkthroo.com

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();
Enter fullscreen mode Exit fullscreen mode

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));
};
Enter fullscreen mode Exit fullscreen mode

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';
Enter fullscreen mode Exit fullscreen mode

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))
Enter fullscreen mode Exit fullscreen mode

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

.otherwise(async () => putFileInDatabase(file));
Enter fullscreen mode Exit fullscreen mode

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 an interesting project. 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

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay