Skip to content

OptionalPropNames<T>: unexpected result in conditional type #21989

@yortus

Description

@yortus

TypeScript Version: 2.8.0-dev.20180216

Code

// Type-level filters to extract just the required or optional properties of a type
// Defns from https://github.com/Microsoft/TypeScript/pull/21919#issuecomment-365491689
type OptionalPropNames<T> = { [P in keyof T]: undefined extends T[P] ? P : never }[keyof T];
type RequiredPropNames<T> = { [P in keyof T]: undefined extends T[P] ? never : P }[keyof T];
type OptionalProps<T> = { [P in OptionalPropNames<T>]: T[P] };
type RequiredProps<T> = { [P in RequiredPropNames<T>]: T[P] };

// Let's extract just the optional property names in a type
type PropNames = OptionalPropNames<{req: string, opt?: number}>;   // Names = "opt" | undefined

Expected behavior:
PropNames = "opt"

Actual behavior:
PropNames = "opt" | undefined. How did that undefined get in there?

Related Issues:
Noticed this while writing up #21988, but wasn't sure if the cause was related or not.

The RequiredProps and OptionalProps definitions come from #21919 (comment)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions