'How can I make one property non-optional in a typescript type?

I have this type:

type User = { 
  id: string;
  name?: string;
  email?: string;
}

And I would like to construct a similar type with name non optional:

type UserWithName = {
  id: string;
  name: string;
  email?: string;
}

Instead of repeating the type as I did above, how can I construct UserWithName from User with generic utility types?
Required almost does the job but it sets all properties as non-optional, while I just want to set one property.



Solution 1:[1]

If you check the source for the Required type, it's this:

type Required<T> = {
  [P in keyof T]-?: T[P]
}

The same syntax can be used to construct a generic type that will give you what you want:

type User = {
  id: string
  name?: string
  email?: string
}

type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] }

type UserWithName = WithRequired<User, 'name'>

// error: missing name
const user: UserWithName = {
  id: '12345',
}

Playground link

Solution 2:[2]

You can use interfaces instead:

interface User  { 
  id: string;
  name?: string;
  email?: string;
}


interface UserWithName extends User {
  name: string;
}

Now you've built on the User type, but overwritten the name property to be mandatory. Check out this typescript playground - a UserWithName that doesn't have a name property will error.

Solution 3:[3]

I improved on the suggestion made at the top.

type Required<T, K extends keyof T> = T & { [P in K]-?: T[P] }

type WithRequired<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>> & Required<T, K>

now you can require multiple properties at once

interface foo {x?: number, y?: String}

WithRequired<foo, 'x' | 'y'>

every property is now required

Solution 4:[4]

I think this is simpler and works pretty well. Given the User type of which you want to make the name property non-optional:

type User = { 
  id: string;
  name?: string;
  email?: string;
}

To create a named interface:

interface UserWithName extends User {
  name: NonNullable<User['name']>
}
let personWithName1: UserWithName;

To create a named type:

type UserWithName = User & {
  name: NonNullable<User['name']>
}
let personWithName2: UserWithName;

To create an anonymous type:

let personWithName3: User & { name: NonNullable<User['name']> }

I like this approach because you don't need to define a new Generic, but you will still benefit from being able to freely change the type of the name property in User, and you will also be shown an error if you ever change the name itself of the name property.

In case you don't fully understand what's going on, I'm using:

Solution 5:[5]

If you need to make a nested property mandatory, an intersection is your friend. Works with both interfaces and types.

// This can be a type too
interface User {
  id: string
  properties: {
    name?: string
    email?: string
  }
}

// Make properties.name mandatory
type UserWithEmail = User & { properties: { name: string } }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Vojt?ch Strnad
Solution 2 Seth Lutske
Solution 3 Maix
Solution 4
Solution 5 Louis Coulet