15

I need an interface for making some fields of other interface as required. For example: I have IUserInterface:

interface IUser {
  name: string;
  role?: string;
}

interface IUserFromDB {
  id: number;
  name: string;
  role: string;
}

When I create new user - role is optional. DB set default role and when I select user from DB - role must be in userObject. I can write Interfaces like I've written above, but in a real project this approach creates a lot of redundant code. So, I need some interface, that help me to get old interface and make some optional fields as required.

I want something like this:

interface IUser {
  name: string;
  role?: string;
}

type IUserFromDB = WithRequired<IUser, 'role'[|...]> & {
  id: number;
  ...;
};

Please help me to create this WithRequired type.

Farad
  • 885
  • 2
  • 9
  • 25

2 Answers2

19

Keeping your IUser interface

Using Partial, Pick, and Required:

interface IUser {
    name: string;
    role?: string;
}

type IUserFromDB = Partial<IUser> & Required<Pick<IUser, 'name' | 'role'>> & {
    id: number;
    ...;
};

In this case the use of Partial is not required unless IUser grows. As it does not affect in run time, I suggest to keep it anyway :)

Alternative approach

With a common fully-required model and using Partial and Pick for any derived type:

interface IUserModel {
    name: string;
    role: string;
}

type IUser = Partial<IUserModel> & Pick<IUserModel, 'name'>; 

type IUserFromDB = Partial<IUserModel> & Pick<IUserModel, 'name' | 'role'> & {
    id: number;
    ...;
};
Community
  • 1
  • 1
Ignacio Lago
  • 2,432
  • 1
  • 27
  • 33
15

You can create a helper type and use it like this:

// Helper type
export type RequiredField<T, K extends keyof T> = T & Required<Pick<T, K>>;


// Use
RequiredField<IUser, 'role'>
Dat V.
  • 183
  • 2
  • 7