Skip to content

Unconstrained generics are incorrectly assignable to _any_ "Partial" type #30634

Description

TypeScript Version: 3.4.0-dev.201xxxxx

Code

declare let x: Partial<HTMLElement>;

function f<T>(y: T) {
    x = y;
}

f({ innerHtml: Symbol() }); // this is blatantly incompatible with `HTMLElement`

if (x.innerHTML) {
    x.innerHTML.toLowerCase(); // We just set it to a `symbol` and not a `string`, this will error at runtime
}

Expected behavior:
An error on x = y.

Actual behavior:
No error.

Playground Link

The root cause is this relationship in structuredTypeRelatedTo added way back in this:

if (relation !== subtypeRelation && isPartialMappedType(target) && isEmptyObjectType(source)) {
    return Ternary.True;
}

This is unsound when source is the empty type resulting from the constraint of an unconstrained generic type (which, if changed to unknown, catches this issue!). It's unsound when it comes from a constraint at all, actually. Fixing this will break react-redux, whose recursive Shared type (which we have in our test suite) actually only checks because of this unsoundness.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScript

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions