Search code examples
typescriptconditional-types

Check if an interface has a required field


Is it possible to check whether an interface has a required field using Typescript's Conditional Types?

type AllRequired = { a: string; b: string }
type PartiallyRequired = { a: string; b?: string }
type Optional = { a?: string; b?: string }

// Is it possible to change this, so the below works
type HasRequiredField<T> = T extends {} ? true : false

type A = HasRequiredField<AllRequired> // true
type B = HasRequiredField<PartiallyRequired> // true
type C = HasRequiredField<Optional> // false

Solution

  • Yes, you can detect if properties are optional. It gets a bit iffy with index signatures, but your types don't have them so I'm not going to worry about them.

    Here's how you can extract just the keys of the non-optional properties of an object type

    type RequiredKeys<T> = { [K in keyof T]-?:
      ({} extends { [P in K]: T[K] } ? never : K)
    }[keyof T]
    

    And then you can just check if it has any of them or not (if RequiredKeys<T> is never then it does not):

    type HasRequiredField<T> = RequiredKeys<T> extends never ? false : true
    

    And that gives your desired results:

    type A = HasRequiredField<AllRequired> // true
    type B = HasRequiredField<PartiallyRequired> // true
    type C = HasRequiredField<Optional> // false
    

    Hope that helps; good luck!