Search code examples
typescripttype-conversionnullablenon-nullabletypescript-types

Strictifying nullable fields for validation


I'm trying to get the compiler to help me with validation of payloads received over the network. So what I want to do is take a JSON payload over the wire and make sure the compiler complains if all the fields are not set. I know the way to do this is to use validation functions but even before I get to the validation part I need to generate some boilerplate that converts a type with nullable fields into a type with strict fields. So the validation functions must have the following signature

type Validator<T> = (i: T) => Strictify<T>;

The problem is that I don't know how to get Strictify to actually work. When I write the following it doesn't work

type Strictify<T> = {
  [K in keyof T]: Exclude<T[K], undefined>
};
type Test = { k?: string };
type StrictTest = Strictify<Test>;

The type of StrictTest should be { k: string } but it's actually still { k?: string }. The interesting part is if I change the definition of Test to { k: string | undefined } then it works. The strictified type is what I expect it to be. Anyone know how to make this all work without expanding every k?: T to k: T | undefined?


Solution

  • Your version would work if the field type were to have been declared as string|undefined. Although under strictNullChecks optional fields are shown as having the type string|undefined they are not the same thing, optionality is a property of the field.

    To remove the optional modifier from the field when using a homomorphic mapped type, starting in typescript 2.8, you can add -? to the type:

    type Strictify<T> = {
      [K in keyof T]-?: Exclude<T[K], undefined>
    };
    type Test = { k?: string };
    type StrictTest = Strictify<Test>;