Required Utility Type in TypeScript
Required<T> removes the optional modifier from every property in a type, making all fields mandatory. Use it when optional defaults are not enough and you need every field present.
The TypeScript Required utility type takes a type with optional properties and makes every one of them mandatory. If a property has a question mark, Required removes it. The result is a type where every field must be provided, no exceptions.
This is useful when you have incomplete data that becomes complete at a specific point in your code. You might accept partial input from a form, validate it, and then treat the validated result as fully populated. Required tells the compiler that the data is now guaranteed to be complete.
interface DraftUser {
name?: string;
email?: string;
age?: number;
}
type CompleteUser = Required<DraftUser>;DraftUser allows any subset of fields. CompleteUser demands all three. If you try to create a CompleteUser without age, the compiler reports a missing property error.
What Required produces
Required removes the optional modifier from every property. Properties that were already required stay the same.
It does not change property types themselves: a string | undefined union stays as-is. The utility only targets the question mark modifier, not undefined inside union types.
interface FormFields {
username: string;
bio?: string;
avatar?: string;
}
type StrictFields = Required<FormFields>;After this transformation, StrictFields is equivalent to { username: string; bio: string; avatar: string }. The required username field is unchanged, and the optional bio and avatar fields lose their question marks.
Required as the inverse of Partial
Required undoes what Partial utility type in TypeScript does. If you apply Partial to a type and then Required to the result, you get the original type back.
interface Task {
title: string;
dueDate: Date;
assignee: string;
}
type BackToOriginal = Required<Partial<Task>>;Partial<Task> makes every property optional. Required then removes all those optional markers, producing the original Task type back. The reverse also holds: wrapping Required inside Partial produces a fully optional type regardless of what the source type looked like.
Where Required is most useful
The strongest use case is at validation boundaries. During a form fill, your data might be partial. After validation runs, every field is confirmed present. Required expresses that transition in the type system.
interface SignupForm {
name?: string;
email?: string;
password?: string;
}Here is a validation function for that SignupForm type. It throws if any field is missing, and its return type promises the caller a fully populated object by wrapping the parameter type in Required:
function validate(form: SignupForm): Required<SignupForm> {
if (!form.name || !form.email || !form.password) {
throw new Error("All fields are required.");
}
return form as Required<SignupForm>;
}After validate returns, the caller gets a type where name, email, and password are all string, not string | undefined. There is no need to check for undefined on every property access. The compiler trusts that validation ran. For more on this pattern, see runtime validation in TypeScript.
Required with configuration objects
Another practical use is filling in defaults and marking the result complete. Accept a Partial configuration from the user, merge defaults, and use Required on the output.
interface Settings {
theme?: string;
notifications?: boolean;
}
function withDefaults(partial: Settings): Required<Settings> {
return {
theme: partial.theme ?? "light",
notifications: partial.notifications ?? true,
};
}
const final = withDefaults({ theme: "dark" });After withDefaults runs, final.notifications is boolean, not boolean | undefined. Every code path after this point can rely on both fields being present.
Required vs writing the type by hand
For small types, you could just rewrite the type without question marks. Required is more valuable for larger types or types you do not control.
| Approach | Good for | Risk |
|---|---|---|
| Rewrite by hand | 2 or 3 properties | Falls out of sync when the source type changes |
| Required | Many properties, library types | None. References the original type directly |
If a library updates its ApiResponse type to add a new field, Required<ApiResponse> includes it automatically. A handwritten copy would miss it.
Common mistakes
Expecting Required to remove | undefined from union types. name?: string is different from name: string | undefined. The first means the property can be absent. The second means the property must be present but its value can be undefined.
Required only removes the optional modifier, not undefined from unions.
Using Required when only some properties should become mandatory. Required is all-or-nothing. If only a subset of fields need to be required, combine Pick and Omit instead, or write a custom mapped type for that specific split.
Forgetting that Required is compile-time only. Adding Required to a type does not validate data at runtime. An object typed as Required<T> might still be missing fields if the data came from an external source without runtime checks.
Rune AI
Key Insights
⚠ This article has a formatting issue and may not display correctly.
Our team has been notified. The content is shown as plain text below.
Frequently Asked Questions
What happens if I use Required on a type with no optional properties?
Does Required affect readonly properties?
Is Required the same as removing the question marks manually?
Conclusion
⚠ This article has a formatting issue and may not display correctly.
Our team has been notified. The content is shown as plain text below.
More in this topic
TypeScript Compiler Explained
The TypeScript compiler (tsc) turns .ts files into .js files while checking types. Learn what it does, how to use it, and how it fits your workflow.
Set Up ESLint for TypeScript
Install and configure ESLint with typescript-eslint to catch bugs and enforce consistent code style in your TypeScript project.
Pick Utility Type in TypeScript
Pick creates a new type by selecting only the properties you name from an existing type. Use it to build focused types for specific views, API responses, or function parameters.