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
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
.