{"id":20033710,"url":"https://github.com/k1eu/typed-formdata","last_synced_at":"2026-02-23T11:05:24.399Z","repository":{"id":252530298,"uuid":"840712977","full_name":"k1eu/typed-formdata","owner":"k1eu","description":"Utility library for working with FormData in Typescript","archived":false,"fork":false,"pushed_at":"2024-08-13T20:15:13.000Z","size":36,"stargazers_count":23,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-07T05:13:43.703Z","etag":null,"topics":["formdata","formdata-format","typescript","typescript-library"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/k1eu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-10T13:07:56.000Z","updated_at":"2025-05-08T11:44:35.000Z","dependencies_parsed_at":"2024-08-10T14:29:06.602Z","dependency_job_id":"a55c2d01-8c8e-4c74-9771-ad1dd7c6e00a","html_url":"https://github.com/k1eu/typed-formdata","commit_stats":null,"previous_names":["k1eu/typed-formdata"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k1eu%2Ftyped-formdata","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k1eu%2Ftyped-formdata/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k1eu%2Ftyped-formdata/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k1eu%2Ftyped-formdata/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/k1eu","download_url":"https://codeload.github.com/k1eu/typed-formdata/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k1eu%2Ftyped-formdata/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":258970201,"owners_count":22786032,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["formdata","formdata-format","typescript","typescript-library"],"created_at":"2024-11-13T09:47:16.027Z","updated_at":"2026-02-23T11:05:24.357Z","avatar_url":"https://github.com/k1eu.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# typed-formdata\n\n`typed-formdata` is a utility library for working with FormData in Typescript.\n\nIn a nutshell, Typed FormData allows you to:\n\n- Work with FormData with strongly typed fields\n- Helpful for both Frontend and Backend work with FormData\n- Integrate it with Full stack typescript frameworks like Remix, Next.js, Nest.js\n- It is a drop-in replacement for FormData\n- It is built on top of the native FormData interface\n- _Parse the formData body according to schema (WIP)_\n\n## Installation\n\n```sh\nnpm install @k1eu/typed-formdata\n```\n\n```sh\nyarn add @k1eu/typed-formdata\n```\n\n```sh\npnpm add @k1eu/typed-formdata\n```\n\n```sh\nbun add @k1eu/typed-formdata\n```\n\n## Overview\n\nPackage can help you both on Frontend and Backend side of the application.\nIt provides a `TypedFormData` class and parser functions for Request and FormData. Of course it is advised to have a validation layer in your backend until we have a schema validator implemented in the library.\n\nRequest handler:\n\n```ts\nimport { TypedFormData } from \"@k1eu/typed-formdata\";\n\ntype IncomingData = {\n  resourceId: string;\n  file: File;\n};\n\nexport const handler = async (req: Request) =\u003e {\n  const formData = parseFormDataRequest\u003cIncomingData\u003e(req);\n  const resourceId: string = formData.get(\"resourceId\");\n  const file: File = formData.get(\"file\");\n  const age: string = formData.get(\"age\"); // Type Error! Age doesn't exist in IncomingData\n\n  saveFile(file, resourceId);\n\n  return new Response(\n    `Hello your file ${file.name} is saved for the resource ${resourceId}`\n  );\n};\n```\n\nFrontend form:\n\n```ts\nimport { TypedFormData } from \"@k1eu/typed-formdata\";\n\ntype MyFormData = {\n  login: string;\n  password: string;\n};\n\nfunction MyPage() {\n  return (\n    \u003cform\n      onSubmit={(e) =\u003e {\n        e.preventDefault();\n        const formData = new TypedFormData\u003cMyFormData\u003e(e.currentTarget);\n        const login: string = formData.get(\"login\");\n        const password: string = formData.get(\"password\");\n        loginAndSubmit(login, password);\n      }}\n    \u003e\n      \u003cinput type=\"login\" name=\"login\" /\u003e\n      \u003cinput type=\"password\" name=\"password\" /\u003e\n      \u003cbutton type=\"submit\"\u003eSubmit\u003c/button\u003e\n    \u003c/form\u003e\n  );\n}\n```\n\nRemix action:\n\n```tsx\nimport { TypedFormData } from \"@k1eu/typed-formdata\";\n\ntype FormFields = {\n  login: string;\n  password: string;\n};\n\nexport async function action({ request }: ActionArgs) {\n  const formData = parseFormDataRequest\u003cFormFields\u003e(request);\n  const login: string = formData.get(\"login\");\n  const password: string = formData.get(\"password\");\n  const file = formData.get(\"file\"); // Type Error!\n  loginAndSubmit(login, password);\n  return redirect(\"/success\");\n}\n\nexport default function MyPage() {\n  return (\n    \u003cmain\u003e\n      \u003cForm method=\"post\"\u003e\n        \u003cinput type=\"login\" name=\"login\" /\u003e\n        \u003cinput type=\"password\" name=\"password\" /\u003e\n        \u003cbutton type=\"submit\"\u003eSubmit\u003c/button\u003e\n      \u003c/Form\u003e\n    \u003c/main\u003e\n  );\n}\n```\n\nOther Parser functions:\n\n```ts\n// parseFormData\nimport { parseFormData } from \"@k1eu/typed-formdata\";\n\ntype FormFields = {\n  resourceId: string;\n  file: File;\n};\n\nconst formData = new FormData(document.querySelector(\"form\"));\nconst typedFormData = await parseFormData\u003cFormFields\u003e(formData);\n\n// same as\n// const typedFormData = new TypedFormData(document.querySelector(\"form\") as HTMLFormElement);\n```\n\n## License\n\nSee [LICENSE](https://github.com/k1eu/typed-formdata/blob/main/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fk1eu%2Ftyped-formdata","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fk1eu%2Ftyped-formdata","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fk1eu%2Ftyped-formdata/lists"}