There is a custom type Options (nested object) that I created. I want to use the type DefaultProperties to create an object that contains the default properties.
type Options = {
id: number,
text: string | undefined,
properties: {
title: string,
subtitle: string | undefined,
}
}
type DefaultProperties = Pick<Options, "properties">;
Of course the default properties cannot be undefined. So I want to exclude undefined from my union types.
For that purpose there should be a build-in functions like NonNullable<T> or Exclude<T,UnionType>.
I tried three different ways to remove undefined but no solution is working with my type.
type Options = {
id: number,
text: string | undefined,
properties: {
title: string,
subtitle: string | undefined,
}
}
type DefaultProperties = Pick<Options, "properties">;
// Try #1: does not work
type Type1 = NonNullable<DefaultProperties>;
// Try #2: does not work
type NotOptional<Type> = {
[Property in keyof Type]-?: Type[Property];
};
type Type2 = NotOptional<DefaultProperties>;
// Try #3: does not work
type Type3 = Exclude<Options, undefined>;
Example: TypeScript Playground
How can I remove all undefineds from all of my type union types?
Edit:
All undefineds should be removed from my type. For example:
Options['text'] : string(No moreundefined)Options['properties']['subtitle'] : string(No moreundefined)
Later I want to use the type for this (for example):
const options : Options = { ... };
const defaults: DefaultProperties= { ... }; // With no undefined
const node : HTMLElement = .... ;
node.innerHTML = options.properties.subtitle !== undefined ? options.properties.subtitle : defaults.properties.subtitle;
When defaults.properties.subtitle has the type string | undefined, the compiler throws an error because innerHTML only allows strings. For that I want to exclude undefined.
CodePudding user response:
You're really close with your NotOptional utility type and Exclude, the problem is that you're defining DefaultProperties as an object with a properties property, but you're trying to remove undefined from DefaultProperties, not from its properties property.
In a comment you've said you want DefaultProperties to be the same shape as properties on Options. That means the basic shape of it (before we try to remove undefined) is Options["properties"]. So:
type NotOptional<Type> = {
[Property in keyof Type]: Exclude<Type[Property], undefined>;
};
type DefaultProperties = NotOptional<Options["properties"]>;
Tests:
const defaults1: DefaultProperties = {
title: "foo",
subtitle: undefined, // <== Error as desired
};
const defaults2: DefaultProperties = {
title: "foo",
subtitle: "something", // <== No error
};
You might also consider removing optionality (combining two of the things you tried):
type NotOptional<Type> = {
[Property in keyof Type]-?: Exclude<Type[Property], undefined>;
};
type DefaultProperties = NotOptional<Options["properties"]>;
Tests:
const defaults1: DefaultProperties = {
title: "foo",
subtitle: undefined, // <== Error as desired (wrong type for `subtitle`)
};
const defaults2: DefaultProperties = { // <== Error as desired (missing `somethingElse`)
title: "foo",
subtitle: "something",
};
const defaults3: DefaultProperties = { // <== No error
title: "foo",
subtitle: "something", // <== No error
somethingElse: "x",
};
