Skip to content

Excess and common property checks don't work correctly with NoInfer #57697

@Andarist

Description

@Andarist

🔎 Search Terms

epc excess common properties weak type noinfer

🕗 Version & Regression Information

  • I was unable to test this on prior versions because NoInfer was introduced in 5.4

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.5.0-dev.20240308#code/CYUwxgNghgTiAEAzArgOzAFwJYHtXwxAGcMBGAHgBV4QAPQ1YI+Ab3loC54SYtUBzeAF8AfAAoAUPHhQulADRT4AIy4A5HAElUiEDCoj4AH3hixASngBeQxu279lEecXmuANxxZgAbgkTCElIxNk54ACJEHBxw4XlWdi5w5VhYoXMfeAB6LJl8PjAcGDhMGgAHMBpiooDiMhDEiKiYuISw5NT4gE8uABYAJmEM7NyQCqqYIpVkDHg8GXgAd0mBeDLJsr0MLv9QSFgEFHRsecCMfqoaehBGZlCuHj5BUUlpWXgFJVV4Ox09A2MPy0f30Fmshicrg8Xl8-jO-Qa7WaaXi9wiKRgaQytRICLRkWiKLaSQx4W6fUG6UyOW4AAscMgIMB4LSoO4EFB8GNKnpJjBduBoHAkGhMLh8GcAMyXOgMJjE7gYXirF5Kd6faTfX4OS4mMyWGwfcwiKHwTzePwSGkYelEBCLIoAayQfBAOIwksRSWRrXxpKGfilXqahN9jQ6mPJ8AGAYF+2FhVQJDWsGwUAgAHllAArUhcAAKqaw6fIbHeaEdqBwi1QmW+FarNeEIj8eyFCETybKRfTWez-QLPYgpfgYC4DertfgwHHqErk+brcFB1HeGTRBwAFsQH28wrHirLW2V0cxac6r0DGJ1fEtcCdU54AAyBLrHBlAD8s-nTfS0ItcIXmI3YwGmmY5qQ8Qbtuu7DDSRD0oyzJwGURSzFWq6bpu8xvmUzC8jUEjHsKp4nBKdQAKxUJBHz9OIapyJBXxyP0ijSGOQL2P8lCkIYL7atxdGmuasLuhRwFDru8QgWBfasdwW47hBcG5AhDJMvAKFofAGGFFhOEbPh1T8kRy4kaKZEEHUABs1HxJQdHXoxt4sfEHECY4pDPrRzj-qJZzWRJoHFuBubSZJObydBSm5ipBC0lgzB4PaTpJY6EhAA

💻 Code

declare function test1<T extends { x: string }>(
  a: T,
  b: NoInfer<T> | (() => NoInfer<T>),
): void;

test1({ x: "foo" }, { x: "bar" }); // an incorrect epc error
test1({ x: "foo" }, { x: "bar", y: 42 }); // epc error but on a wrong property

declare function test2<T extends { x: string }>(
  a: T,
  b: NoInfer<T> | NoInfer<() => T>,
): void;

test2({ x: "foo" }, { x: "bar" });
test2({ x: "foo" }, { x: "bar", y: 42 }); // should have an epc error

declare function test3<T extends { x: string }>(
  a: T,
  b: NoInfer<T | (() => T)>,
): void;

// those work fine
test3({ x: "foo" }, { x: "bar" });
test3({ x: "foo" }, { x: "bar", y: 42 });

declare const partialObj1: Partial<{ a: unknown; b: unknown }>;
declare const partialObj2: Partial<{ c: unknown; d: unknown }>;
declare const someObj1: { x: string };

declare function test4<T>(a: T, b: NoInfer<T> & { prop?: unknown }): void;

test4(partialObj1, someObj1); // should report no common props error

declare function test5<T1, T2>(
  a: T1,
  b: T2,
  c: NoInfer<T1> & NoInfer<T2>,
): void;

test5(partialObj1, partialObj2, someObj1); // should report no common props error

declare function test6<T1, T2>(a: T1, b: T2, c: NoInfer<T1 & T2>): void;

test6(partialObj1, partialObj2, someObj1); // this one works ok

🙁 Actual behavior

Excess property check doesn't work properly when union members are wrapped by NoInfer individually. Similarly common properties check doesn't work properly with intersections when its members are wrapped by NoInfer individually

🙂 Expected behavior

I've annotated the playground with expected results where appropriate

Additional information about the issue

this open PR fixes it: #57673

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScript

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions