Parse FormData into a structured JavaScript object with coerced primitives including TypeScript support
npm install formdata-helper> Parse FormData into a structured JavaScript object with coerced primitives
``ts
// Optional: Add TypeScript typing to the response values.
type SignUp = {
email: string;
password: string;
age: number;
terms: boolean;
// With multi-select type fields, choosing one item will result in a string value.
favorites: string | string[];
resume: File;
};
// Create some FormData. You likely will just pass form data
// and not manually create it like this.
const formData = new FormData();
formData.set("email", "hi@example.com");
formData.set("password", "s3kret!");
formData.set("age", "29");
formData.set("terms", "true");
formData.append("favorites", "TypeScript");
formData.append("favorites", "Svelte");
formData.set(
"resume",
new File(["Did lots of stuff"], "resume.txt", { type: "text/plain" })
);
const data = parseForm
// Returns the following structured data:
data.email; // "hi@example.com"
data.password; // "s3kret!"
data.age; // 29
data.terms; // true
data.favorites; // ["TypeScript", "Svelte"]
data.resume; // File { name: "resume.txt", type: "text/plain" }
`
Sometimes, working with FormData can be a pain in the bum, especially when working with large forms or when lots of form data needs to be coerced.
This simple tool takes an instance of FormData and returns a structured JavaScript object with coerced values of primitive types (boolean, number) and creates Arrays for grouped fields like multi-selects and multiple checkboxes. FormData is used in a lot of places where you may need to interact with its values:
- new FormData(document.querySelector("form"))+server
- WebWorker
- SvelteKit or +page.server responses
- Etc...
This library _should_ work in all these cases, if it doesn't, please open an
issue!
You can use the data parsed by formdata-helper to pass to your validation
logic, say using Zod.
- Coerces various common value types into an Object:"on"
- (for checkboxes), and "true" and "false" are coerced to booleans which is the value a type="checkbox" or type="radio" field will return."1.5"
- Numbers strings are converted to numbers (e.g. becomes 1.5)"hello1"
- Strings with numbers will not (e.g. , "1hello" or "he11o" will be strings)
- Grouped fields like multi
And some things that are beyond the scope of this library:
- Doesn't validate the incoming data. For that, checkout Zod, Yup, io-ts, Runtypes or joi
- Doesn't look at what field types you have and intelligently parse them. Since FormData doesn't give us this type of information, there is nothing we can know about the data in it, so we just do a naive parsing of the data. If you need something more robust, look elsewhere!
- Since we don't know the types of the data, if a field is empty, it will always be resolved to an empty string. Keep this in mind when working with the data.
`shell`
npm i formdata-helper
Assuming the following form data:
`html`
parseFormData will return a structured JavaScript object:
`ts
import { parseFormData } from "formdata-helper";
const formData = new FormData(document.querySelector("form"));
const data = parseFormData(formData);
`
data becomes:
`js`
{
name: "Jane Doe",
favoriteFruits: [ "Banana", "Mango" ],
}
Passing custom configuration options (all are shown below):
`ts
const formData = new FormData()
formData.append("email": "hi@example.com")
formData.append("likesTypeScript": "yes") // will coerce to true with the below truthy option.name
// will get automatically set with defaults option.
parseFormData(formData, {
defaults: { name: "Guest" },
falsy: ["false", "f"],
truthy: ["yes", "y"],
});
`
`tsFormData
/**
* Define a return type for the data.
* Note that return value is actually Partial
* we cannot guarantee the presence of any values in the provided undefined
* so all return values are possibly .
*/
type MyFormData = {
username: string;
age: number;
// Any multi-select or group of checkboxes can be either a
// single string or an array of strings.
interests: string | string[];
admin: boolean;
};
// With all options:
parseFormData
defaults: {
username: "guest",
interests: ["TypeScript"],
admin: false,
},
});
`
Please note that if you want to use an interface instead of a type, you haveextend
to from StructuredFormData type exported from this package:
`ts
import { StructuredFormData } from "formdata-helper";
interface MyFormData extends StructuredFormData {
username: string;
age: number;
interests: string[];
admin: boolean;
}
`
You can use this helper in your +server and +page.server files to parse
incoming form data from form submissions in your Svelte pages.
`ts
import subscribeUser from "./subscribe-user";
import { parseFormData } from "formdata-helper";
import type { RequestHandler } from "./$types";
import { json } from "@sveltejs/kit";
type RequestData = {
email: string;
subscribe: boolean;
};
export const POST: RequestHandler = async ({ request }) => {
const formData = await request.formData();
const data = parseFormData
if (data.subscribe && data.email) {
await subscribeUser(data.email);
}
return json(data);
};
`
Type signatures:
`ts
type StructuredFormValue =
| string
| boolean
| number
| File
| StructuredFormValue[];
type StructuredFormData = Record
interface Configuration
defaults?: Partial
falsy?: string | string[];
truthy?: string | string[];
}
parseFormData
`
- Tests are run with npm test using Vitesttsup.config.ts`)
- Code is written in TypeScript
- Build tool is tsup (see
- Releases are done using changesets
MIT
Created by Dana Woodman