typescripttypesnullablenon-nullablerequired-field

Typescript type RequireSome<T, K extends keyof T> removing undefined AND null from properties


RequireSome type from another, very simialar question. This question is similar but it should not be a duplicate since here we want to also remove null as well as undefined from properties.

Maybe the name shouldn't be Require but something like NonNullable or of this kind. The goal of this type is to specify which fields from a type should not be undefined or null, and return their types without undefined and null.

type Question = {
    id: string;
    answer?: string | null;
    thirdProp?: number | null;
    fourthProp?: number | null;
}

// usage NonNullable<Question, 'answer' | 'thirdProp'> expect to equal
/*

type Question = {
    id: string; // no changes
    answer: string; // changed
    thirdProp: number; // changed
    fourthProp?: number | null; // no changes
}

*/

Solution

  • The simplified approach that just intersects with T with Required<Pick<T, K>> with the required part basically overriding the optional properties in T will not work here. (Incidentally this works because { foo?: X } & { foo: X } is essentially { foo: X })

    To also remove nullability, we have to first create a type that removed null and undefined from a given type T (analogous to Required). Then we need to intersect the properties we want to make required and not null with the rest of the keys in T using the Omit type.

    type Omit<T, K> = Pick<T, Exclude<keyof T, K>> // not needed in ts 3.5
    
    type RequiredAndNotNull<T> = {
        [P in keyof T]-?: Exclude<T[P], null | undefined>
    }
    
    type RequireAndNotNullSome<T, K extends keyof T> = 
        RequiredAndNotNull<Pick<T, K>> & Omit<T, K>
    
    type Question = {
        id: string;
        answer?: string | null;
        thirdProp?: number | null;
        fourthProp?: number | null;
    }
    
    type T0 = RequireAndNotNullSome<Question, 'answer' | 'thirdProp'>