Skip to content

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

Open
@weswigham

Description

@weswigham

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.

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