Skip to content

difference in typecheck with 5.8 (intersection of types breaks some compatibility) #799

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
dartess opened this issue Apr 15, 2025 · 1 comment
Assignees

Comments

@dartess
Copy link

dartess commented Apr 15, 2025

Same errors, locations, and messages as TS5.8

yet another little difference
(types are mostly copied from remeda)

type IterableContainer<T = unknown> = ReadonlyArray<T> | readonly [];
type Mapped<T extends IterableContainer, K> = {
  -readonly [P in keyof T]: K;
};
declare function pipe<A, B>(value: A, op1: (input: A) => B): B;
declare function map<T extends IterableContainer, U>(
  callbackfn: (value: T[number], index: number, data: T) => U,
): (data: T) => Mapped<T, U>;

type Point = { x?: number } & { y?: number };

export function update(modify?: (point: Point) => Point) {
  return pipe(
    [{ x: 0 }],
    modify
      ? map(modify)
      : map((point) => point),
  );
}
error TS2345: Argument of type '((data: { x: number; }[]) => { x: number; }[]) | ((data: { x: number; }[]) => Point[])' is not assignable to parameter of type '(input: { x: number; }[]) => { x: number; }[]'.
  Type '(data: { x: number; }[]) => Point[]' is not assignable to type '(input: { x: number; }[]) => { x: number; }[]'.
    Type 'Point[]' is not assignable to type '{ x: number; }[]'.
      Type 'Point' is not assignable to type '{ x: number; }'.
        Types of property 'x' are incompatible.
          Type 'number | undefined' is not assignable to type 'number'.
            Type 'undefined' is not assignable to type 'number'.

16     modify
       ~~~~~~
17       ? map(modify)
   ~~~~~~~~~~~~~~~~~~~
18       : map((point) => point),
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

TS 5.8 is OK with that: playground

If we merge { x?: number } & { y?: number } as { x?: number; y?: number } the error disappears (but in my core I merge different types).

@ahejlsberg ahejlsberg self-assigned this Apr 25, 2025
@ahejlsberg ahejlsberg added the bug Something isn't working label Apr 25, 2025
@ahejlsberg
Copy link
Member

ahejlsberg commented Apr 26, 2025

This turns out to be the same issue as in #798. In the call to pipe we infer two candidates for B: { x: number }[] and Point[]. Neither is a supertype of the other, so inference picks the "first" candidate. With tsc this happens to be Point[], but due to differences in type ordering, with tsgo it is { x: number }[]. Unfortunately, the only inference that actually works out is Point[], so an error results with tsgo. It's entirely possible that there is some reordering of declarations that would also cause the error to occur with tsc.

The issue is easy to work around by adding a type assertion to the first argument, as in [{ x: 0 }] as Point[]. Again, ideally our inference algorithm would do better here, but there's no immediately apparent fix. There is some interesting discussion on the topic in this issue: microsoft/TypeScript#40665.

@ahejlsberg ahejlsberg removed the bug Something isn't working label Apr 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants