-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Regression: Intersection of array and tuple not assignable to tuple #38348
Comments
Also applies to |
I believe that this is because we no longer just consider intersections to be assignable if any constituent is assignable - the type has to be compatible as a whole. @ahejlsberg made that change at #37195 Is there a specific reason you had a |
The issue here is that we lack the ability to relate a tuple type with a rest element on the target side to anything but another tuple type on the source side. In the extra check introduced by #37195, the source type is an intersection, and so the check fails. I think an easy and reasonable fix is to omit the extra check when the target is a tuple type with a rest element. |
I can see it's correct that For example, this works in Nightly: const y: { x: 1 } & { x: number } = { x: 1 };
const x: { x: 1 } = y; Even though |
Apologies, I didn't motivate this very well! The example was perhaps too minimal. The full code looked more like this (reworked to a vaguely minimal example). I hope you can see what was being attempted. No apologies made for the code - it is what it is - and thinking some more I can see that the types could be improved, but it's less clear what's going on in the original code which is a bit more involved. type Checker<T> = (x: unknown) => x is T;
type NonEmptyArray<T> = [T, ...T[]];
function bothChecker<T1, T2>(c1: Checker<T1>, c2: (x: T1) => Checker<T2>): Checker<T1 & T2> {
return (x: unknown): x is T1 & T2 => c1(x) && c2(x)(x);
}
const numChecker: Checker<number> = (x: unknown): x is number => typeof x === 'number';
function arrayChecker<T>(elt: Checker<T>): Checker<T[]> {
return (x: unknown): x is T[] => Array.isArray(x) && x.every(i => elt(i));
}
function nonEmptyChecker<T>(): Checker<NonEmptyArray<T>> {
return (x: unknown): x is NonEmptyArray<T> => (x as T[]).length > 0;
}
const theProblem: Checker<NonEmptyArray<number>> = bothChecker(
arrayChecker(numChecker),
_asArray => nonEmptyChecker()
); |
Wow, thank you so much for a quick fix! |
TypeScript Version: Nightly
Search Terms: tuple intersection array
Expected behavior:
Expected code to compile. It does compile with
tsc
3.8, but does not compile withtsc
3.9 (Nightly).Actual behavior:
In the code below, the following error is reported:
Code
Discussion
Presumably, this is related to the breaking change in 3.9 around handling of tuple types more strictly. I believe the code is correct however and should compile, because the array type
number[]
is a strict supertype of the tuple type[number, ...number[]]
(surely?) - perhaps the special case unifying tuple types with matching element types to an array type hasn't been implemented?Discovered by @JasonGore and @NWilson (MSFT).
Output
Compiler Options
Playground Link: Provided
The text was updated successfully, but these errors were encountered: