0

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
}

*/
ZenVentzi
  • 3,945
  • 3
  • 33
  • 48

1 Answers1

3

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'> 
ZenVentzi
  • 3,945
  • 3
  • 33
  • 48
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
  • Interesting.. and working as expected :)! Just the answer prop and thirdProp are missing ?: and | null, otherwise it works correctly. `answer?: string | null` `thirdProp?: number | null` – ZenVentzi Apr 15 '19 at 08:38
  • @ZenVentzi not sure I understand your comment. Does it work as you expect it or not ? my understanding was that you wanted optionality, `null` and `undefined` removed from the listed properties, and from what I see it does – Titian Cernicova-Dragomir Apr 15 '19 at 08:41
  • it works exactly as expected. I just wanted to point out that you've missed to add null and undefined to the answer and thirdProp, like it is in my code example above. I.e. `RequireAndNotNullSome` works as expected but with the `type Question` from your example, it doesn't make any difference because answer and thirdProp are not null and undefined anyway. Let me know if I need to explain myself more clearly! – ZenVentzi Apr 15 '19 at 08:45