Skip to content

Inlining definition of NonNullable<T> results in different behavior #23046

Closed
@farnoy

Description

@farnoy

Apologies if this was submitted already, I could not find anything similar by searching.

TypeScript Version: 2.8.1

Search Terms: Existential types, undefined, Exclude, Required, NonNullable, in keyof

Code

type OnlyPresentV1<T> = {
    [P in keyof T]: NonNullable<T[P]>
};

// should pass, and it does
const Test_1: OnlyPresentV1<{test: string}> = {test: "asd"};
// should fail, and it does
const Test_2: OnlyPresentV1<{test: string}> = {test: undefined};
// should pass, and it does
const Test_3: OnlyPresentV1<{test: string | undefined}> = {test: "asd"};
// should fail, and it does
const Test_4: OnlyPresentV1<{test: string | undefined}> = {test: undefined};

type OnlyPresentV2<T> = {
    [P in keyof T]: T[P] extends null | undefined ? never : T[P] 
};

// should pass, and it does
const Test_5: OnlyPresentV2<{test: string}> = {test: "asd"};
// should fail, and it does
const Test_6: OnlyPresentV2<{test: string}> = {test: undefined};
// should pass, and it does
const Test_7: OnlyPresentV2<{test: string | undefined}> = {test: "asd"};
// should fail, but it doesn't!
const Test_8: OnlyPresentV2<{test: string | undefined}> = {test: undefined};

Expected behavior:
I noted down what my expectations are above each case.
I expected that inlining the definition of NonNullable would be the same as using the type.

Actual behavior:
Behavior is different, but definitions are essentially the same?

Playground Link: https://goo.gl/fWzwzA (shortend it because it was really long) Enabled all strictness checks I could

Related Issues: Could not find any

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions