Skip to content

Incompatible code unexpectedly compiles due to intersection with empty mapped type #19869

Closed
@kpdonn

Description

@kpdonn

TypeScript Version: Version 2.7.0-dev.20171109

Code

type Args<S extends string, N extends string> = Record<S, string> & Record<N, number>

declare function f1<S extends string, N extends string>
    (strs: S[], nums: N[], fun: (args: Args<S, N>) => void): void

declare function takesNum(args: {a: number}): void
declare function takesOptionalNum(args: {a?: number}): void

f1(["a"], [], takesNum) // *** unexpectedly compiles despite incompatibility of "a" ***
f1(["a"], ["b"], takesNum) // Now correctly errors because of incompatibility of "a"

f1(["a"], [], takesOptionalNum) // *** unexpectedly compiles despite incompatibility of "a" ***
f1(["a"], ["b"], takesOptionalNum) // Now correctly errors because of incompatibility of "a"

Expected behavior:
All calls to f1 should error because takesNum and takesOptionalNum expect a to be a number but it will actually be a string.

Actual behavior:
It only errors if the second argument to f1 is not empty.

Also the first case shown above: f1(["a"], [], takesNum) actually errored as expected as recently as last week(I believe I was on 2.7.0-dev.20171031), it was only the optional case that unexpectedly compiled. I was about to open this for just the optional case when I checked the latest typescript version and noticed the first case started being affected also.

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