Home > Net >  Is it possible to make a property required, yet preserve undefined
Is it possible to make a property required, yet preserve undefined

Time:05-28

I've tried removing the optional modifier with -? but it appears to treat undefined and optional as the same thing:

interface Props {
  firstName?: string | undefined;
  lastName?: string;
}

// Built-in
// type Required<T> = {
//   [P in keyof T]-?: T[P];
// };

type RequiredProps = Required<Props>;

// EXPECT:
// { firstName: string | undefined; lastName: string; }

// ACTUAL:
// { firstName: string; lastName: string; }

The following question is very similar, however (there is a clear the accepted answer implies the ques

Similar but different questions

How to prevent `Required<T>` in typescript from removing 'undefined' from the type when using --strictNullChecks

Question sounds similar, but they don't give a clear expected input / output and the accepted answer doesn't result in the expected output I've defined above. e.g.

interface Props {
  firstName?: string | undefined;
  lastName?: string;
}

type RequiredKeepUndefined<T> = { [K in keyof T]-?: [T[K]] } extends infer U
  ? U extends Record<keyof U, [any]> ? { [K in keyof U]: U[K][0] } : never
  : never;

type RequiredProps = Required<Props>;

// EXPECT:
// { firstName: string | undefined; lastName: string; }

// ACTUAL:
// { firstName: string | undefined; lastName: string | undefined; }

CodePudding user response:

You can use the exactOptionalPropertyTypes compiler flag to tell TypeScript to disallow assigning undefined to optional properties. This also has the effect of treating T | undefined in an optional property as literally T | undefined. Previously, it would've just been T.

Here their example shows:

interface UserDefaults {
  // The absence of a value represents 'system'
  colorThemeOverride?: "dark" | "light";
}

const settings = getUserSettings();
settings.colorThemeOverride = "dark";
settings.colorThemeOverride = "light";
 
// But not:
settings.colorThemeOverride = undefined;
// ^ Type 'undefined' is not assignable to type '"dark" | "light"' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the type of the target.

And it works as you can see here, it makes firstName the type string | undefined instead of just string.

  • Related