From cf738b9306fbc073f01f9820db7aff193406d366 Mon Sep 17 00:00:00 2001 From: Amruth Pillai Date: Sat, 4 Jul 2026 19:52:13 +0200 Subject: [PATCH] refactor(pdf): replace ts-pattern match chains with satisfies Record maps Two match chains in sections.tsx are replaced with plain lookup maps typed via `satisfies Record` which preserves compile-time exhaustiveness without the ts-pattern dependency. Remove ts-pattern from packages/pdf/package.json. Claude-Session: https://claude.ai/code/session_012Bnvt1MghwHj4qQRxuQUGa --- packages/pdf/package.json | 3 +- .../pdf/src/templates/shared/sections.tsx | 100 +++++++++--------- pnpm-lock.yaml | 3 - 3 files changed, 52 insertions(+), 54 deletions(-) diff --git a/packages/pdf/package.json b/packages/pdf/package.json index 7d8ab648d..d7884c640 100644 --- a/packages/pdf/package.json +++ b/packages/pdf/package.json @@ -28,8 +28,7 @@ "node-html-parser": "^8.0.4", "phosphor-icons-react-pdf": "^0.1.3", "react": "^19.2.7", - "react-pdf-html": "^2.1.5", - "ts-pattern": "^5.9.0" + "react-pdf-html": "^2.1.5" }, "devDependencies": { "@react-pdf/types": "^2.11.1", diff --git a/packages/pdf/src/templates/shared/sections.tsx b/packages/pdf/src/templates/shared/sections.tsx index cddc92314..7d3811393 100644 --- a/packages/pdf/src/templates/shared/sections.tsx +++ b/packages/pdf/src/templates/shared/sections.tsx @@ -3,6 +3,7 @@ import type { AwardItem, CertificationItem, CoverLetterItem, + CustomSectionType, EducationItem, ExperienceItem, InterestItem, @@ -22,7 +23,6 @@ import type { ReactNode } from "react"; import type { StyleInput, TemplatePlacement } from "./styles"; import type { CustomItemSection, ItemSection } from "./types"; import { Children, createContext, isValidElement, use } from "react"; -import { match } from "ts-pattern"; import { View } from "#react-pdf-renderer"; import { useRender } from "../../context"; import { getResumeSectionIcon } from "../../section-icon"; @@ -929,51 +929,50 @@ const CustomSection = ({ sectionId, showHeading = true }: CustomSectionProps) => if (!customSection) return null; - return match(customSection.type) - .with("summary", () => ( + // ponytail: satisfies Record gives compile-time exhaustiveness without ts-pattern + const customSectionMap = { + summary: () => ( } showHeading={showHeading} /> - )) - .with("profiles", () => ( + ), + profiles: () => ( } /> - )) - .with("experience", () => ( + ), + experience: () => ( } /> - )) - .with("education", () => ( + ), + education: () => ( } /> - )) - .with("projects", () => ( + ), + projects: () => ( } /> - )) - .with("skills", () => ( - } /> - )) - .with("languages", () => ( + ), + skills: () => } />, + languages: () => ( } /> - )) - .with("interests", () => ( + ), + interests: () => ( } /> - )) - .with("awards", () => ( - } /> - )) - .with("certifications", () => ( + ), + awards: () => } />, + certifications: () => ( } /> - )) - .with("publications", () => ( + ), + publications: () => ( } /> - )) - .with("volunteer", () => ( + ), + volunteer: () => ( } /> - )) - .with("references", () => ( + ), + references: () => ( } /> - )) - .with("cover-letter", () => } />) - .exhaustive(); + ), + "cover-letter": () => } />, + } satisfies Record ReactNode>; + + return customSectionMap[customSection.type](); }; export const Section = ({ section, placement, showHeading = true }: SectionProps) => { @@ -981,26 +980,29 @@ export const Section = ({ section, placement, showHeading = true }: SectionProps if (!isSectionVisible(section, data)) return null; + // ponytail: satisfies exhaustiveness over built-in types; custom IDs fall through to CustomSection + const builtInSectionMap = { + summary: () => , + profiles: () => , + experience: () => , + education: () => , + projects: () => , + skills: () => , + languages: () => , + interests: () => , + awards: () => , + certifications: () => , + publications: () => , + volunteer: () => , + references: () => , + } satisfies Record, () => ReactNode>; + + const render = (builtInSectionMap as Record ReactNode) | undefined>)[section]; + return ( - {match(section) - .with("summary", () => ) - .with("profiles", () => ) - .with("experience", () => ) - .with("education", () => ) - .with("projects", () => ) - .with("skills", () => ) - .with("languages", () => ) - .with("interests", () => ) - .with("awards", () => ) - .with("certifications", () => ) - .with("publications", () => ) - .with("volunteer", () => ) - .with("references", () => ) - .otherwise(() => ( - - ))} + {render ? render() : } ); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3c4618524..2091c393d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -947,9 +947,6 @@ importers: react-pdf-html: specifier: ^2.1.5 version: 2.1.5(@react-pdf/renderer@4.5.1(react@19.2.7))(react@19.2.7) - ts-pattern: - specifier: ^5.9.0 - version: 5.9.0 devDependencies: '@react-pdf/types': specifier: ^2.11.1