Skip to content

Conditional Types - Checking extends never only works sometimes #23182

@dsherret

Description

@dsherret

TypeScript Version: 2.9.0-dev.20180405

Search Terms: "extends never"

Code

I am writing a function for testing conditional types and I'd like to write it like this:

function assert<T extends true>(expectTrue: T extends never ? false : true) {
}

// or even
function assert<T extends true>(expectTrue: T extends true ? true : false) {
}

That way I can write:

type IsNullableType<T> = T extends null | undefined ? true : never;

const result = functionUnderTest(someParam);

assert<IsNullableType<typeof result>>(true);
// or
assert<IsNullableType<typeof result>>(false);

So given this:

assert<IsNullableType<string>>(false);

Expected behavior:

  • The type of the parameter resolves to false.
  • No error.

Actual behavior:

  • The type of the parameter resolves to never.
  • false is not assignable to never.

Example where extends never works:

type IsNonNullableType<T> = IsNullableType<T> extends never ? true : never;
assert<IsNonNullableType<string>>(true); // no compile error, works fine

// this doesn't cause a compile error in playground, but it correctly throws a compile error in the latest version
assert<IsNonNullableType<string | undefined>>(true); // compile error, as expected

Playground Link: Link.

Basically, an IsNeverType check does not work: type IsNeverType<T> = T extends never ? true : never;


Edit: By the way, this is probably a better way to do my check:

export type IsNullableType<T> = Extract<T, null | undefined> extends never ? false : true;

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions