Home > Web Front-end > JS Tutorial > body text

Optional vs. Undefined: How To Check for Optional Properties

WBOY
Release: 2024-07-28 02:36:43
Original
657 people have browsed it

Optional vs. Undefined: How To Check for Optional Properties

In TypeScript, a property is considered optional if it can be omitted from an object, meaning it can be either undefined or not provided at all. Optional properties are denoted using the ? suffix on the property key. Determining whether a property is optional or explicitly defined with undefined as its type can be quite tricky.

Let's consider the following example with five possible combinations:

type Example = {
    required: number;
    optional?: number;
    requiredAsUndefined: undefined;
    requiredWithUndefined: number | undefined;
    optionalWithUndefined?: number | undefined;
}
Copy after login

The last four properties are allowed to be undefined, but only the second and fifth are actually optional. Interestingly, the properties optional, requiredWithUndefined, and optionalWithUndefined all resolve to the same union type number | undefined.

So, what we want is a type that returns true for optional and optionalWithUndefined, and false for the rest. Here's how such a utility type can look:

type IsOptional<T, K extends keyof T> = undefined extends T[K]
    ? ({} extends Pick<T, K> ? true : false)
    : false;

type Required = IsOptional<Example, 'required'>;  // false
type Optional = IsOptional<Example, 'optional'>;  // true
type RequiredAsUndefined = IsOptional<Example, 'requiredAsUndefined'>;  // false
type RequiredWithUndefined = IsOptional<Example, 'requiredWithUndefined'>;  // false
type OptionalWithUndefined = IsOptional<Example, 'optionalWithUndefined'>;  // true
Copy after login

There are two constraints in this utility type. The first constraint, undefined extends T[K], checks if undefined can be a part of the type accessed by T[K]. It essentially asks whether the type T[K] can include undefined. The second constraint, {} extends Pick ? true : false, ensures that the type {} (an empty object) is assignable to a type where the property K is picked, implying the property is optional.

From this utility type, we can build a new mapped type which only picks optional properties. The non-optional properties will be set to never:

type OptionalProperties<T> = {
    [K in keyof T]: IsOptional<T, K> extends true 
        ? T[K] 
        : never
}

type OnlyOptionals = OptionalProperties<Example>;
// type OnlyOptionals = {
//     required: never;
//     optional?: number;
//     requiredAsUndefined: never;
//     requiredWithUndefined: never;
//     optionalWithUndefined?: number | undefined;
// }
Copy after login

Having the properties with type never is usually enough for type safety, but in case we truly want to omit these properties for stylistic purposes, we can move the IsOptional extends true constraint into the square brackets. This is a nice little trick because it will set the key of non-optional properties to never, which will then get omitted by TypeScript automatically.

type OnlyOptionals<T> = {
    [K in keyof T as IsOptional<T, K> extends true ? K : never]: T[K]
} 
type OnlyOptionals = OnlyOptionals<Example>;
// type OnlyOptionals = {
//    optional?: number;
//    optionalWithUndefined?: number | undefined;
// }
Copy after login

Here's the Playground to try it out directly in the browser: TypeScript Playground

The above is the detailed content of Optional vs. Undefined: How To Check for Optional Properties. For more information, please follow other related articles on the PHP Chinese website!

source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template