How the TypeScript Required Type Works

Johnny Simpson - Apr 6 '22 - - Dev Community

In TypeScript, we sometimes need to enforce that an object has required properties, even if the original type defined some of them as optional. For that, TypeScript has a utility type called Required. Let's look at how it works.

TypeScript Required Utility Type

By default, if we define a new type in TypeScript, all fields within that type are automatically required:

type User = {
    firstName: string,
    lastName: string
}

let firstUser:User = {
    firstName: "John"
}
Enter fullscreen mode Exit fullscreen mode

Above, firstUser is of type User, but it's missing lastName. As such, this code returns an error:

Property 'lastName' is missing in type '{ firstName: string; }' but required in type 'User'.
Enter fullscreen mode Exit fullscreen mode

If we expect a field to be optional, we can add a question mark to the end of it in our type definition. Below, we make lastName optional by writing lastName? instead:

type User = {
    firstName: string,
    lastName?: string
}

let firstUser:User = {
    firstName: "John"
}
Enter fullscreen mode Exit fullscreen mode

As such, this code does not throw an error - lastName is optional, so the fact that firstUser doesn't contain it is fine.

Forcing optional types to be required in TypeScript
Sometimes, we have a situation where most of the time, lastName is optional, but in some circumstances we require it to do something. In these cases, we can use the utility type Required. For example, if we want lastName to be required, even if it was originally defined as optional, we can write the following:

type User = {
    firstName: string,
    lastName?: string
}

let firstUser:User = {
    firstName: "John",
}

let secondUser:Required<User> = {
    firstName: "John"
}
Enter fullscreen mode Exit fullscreen mode

In this example, secondUser throws an error:

Property 'lastName' is missing in type '{ firstName: string; }' but required in type 'Required<User>'
Enter fullscreen mode Exit fullscreen mode

So since we've used Required, we have to add lastName to avoid the error:

type User = {
    firstName: string,
    lastName?: string
}

let secondUser:Required<User> = {
    firstName: "John",
    lastName: "Doe"
}
Enter fullscreen mode Exit fullscreen mode

This can give us more flexibility, while allowing us to enforce field requirements for certain functionality in an application. As with other utility types, Required is meant to work with an interface or object type, like the User type we defined above. As such, it doesn't work with variables. This doesn't matter much, though, since a variable cannot have an empty value anyway.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .