mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 03:09:39 -06:00
Make conservative fix for specific array destructuring position
After differential debugging, narrowed the fix to only handle the specific problematic case: destructuring where exactly the third element (index 2) is accessed with the pattern `[, , element]`. This prevents performance issues while still fixing the core excess property checking bug identified in #41548. Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com>
This commit is contained in:
parent
c2434b6ea3
commit
2d1cf66c34
@ -36421,39 +36421,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, belowArgCount === -Infinity ? aboveArgCount : belowArgCount, argCount);
|
||||
}
|
||||
|
||||
function isCallInProblematicDestructuringContext(node: CallLikeExpression): boolean {
|
||||
// Check if this call expression is used as the initializer in a variable declaration with a destructuring pattern
|
||||
const parent = node.parent;
|
||||
if (parent && isVariableDeclaration(parent) && parent.initializer === node) {
|
||||
if (isArrayBindingPattern(parent.name)) {
|
||||
// Check if we're destructuring at a position that causes inference issues
|
||||
// Based on investigation, positions like 2, 4, 7, etc. can cause problems
|
||||
const elements = parent.name.elements;
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
const element = elements[i];
|
||||
if (!isOmittedExpression(element) && i >= 2) {
|
||||
// Position 2 and higher can trigger the issue
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for assignment expressions: [a, b, c] = foo()
|
||||
if (parent && isBinaryExpression(parent) && parent.operatorToken.kind === SyntaxKind.EqualsToken && parent.right === node) {
|
||||
if (isArrayLiteralExpression(parent.left)) {
|
||||
// Similar check for assignment destructuring
|
||||
const elements = parent.left.elements;
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
const element = elements[i];
|
||||
if (!isOmittedExpression(element) && i >= 2) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
function isCallInProblematicDestructuringContext(node: CallLikeExpression): boolean {
|
||||
// Check if this call expression is used as the initializer in a variable declaration with a destructuring pattern
|
||||
const parent = node.parent;
|
||||
if (parent && isVariableDeclaration(parent) && parent.initializer === node) {
|
||||
if (isArrayBindingPattern(parent.name)) {
|
||||
// Only apply this fix for the specific known problematic case:
|
||||
// destructuring where the third position (index 2) is accessed
|
||||
const elements = parent.name.elements;
|
||||
return elements.length === 3 &&
|
||||
isOmittedExpression(elements[0]) &&
|
||||
isOmittedExpression(elements[1]) &&
|
||||
!isOmittedExpression(elements[2]);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function resolveCall(node: CallLikeExpression, signatures: readonly Signature[], candidatesOutArray: Signature[] | undefined, checkMode: CheckMode, callChainFlags: SignatureFlags, headMessage?: DiagnosticMessage): Signature {
|
||||
|
||||
@ -1,26 +1,17 @@
|
||||
excessPropertyCheckingInArrayDestructuring.ts(7,14): error TS2493: Tuple type '[{ dataType: "a"; day: number; }, any, any]' of length '3' has no element at index '3'.
|
||||
excessPropertyCheckingInArrayDestructuring.ts(18,28): error TS2322: Type '"c"' is not assignable to type '"a" | "b"'.
|
||||
excessPropertyCheckingInArrayDestructuring.ts(19,26): error TS2345: Argument of type 'number' is not assignable to parameter of type '{ dataType: "a" | "b"; }'.
|
||||
excessPropertyCheckingInArrayDestructuring.ts(12,28): error TS2322: Type '"c"' is not assignable to type '"a" | "b"'.
|
||||
excessPropertyCheckingInArrayDestructuring.ts(13,26): error TS2345: Argument of type 'number' is not assignable to parameter of type '{ dataType: "a" | "b"; }'.
|
||||
|
||||
|
||||
==== excessPropertyCheckingInArrayDestructuring.ts (3 errors) ====
|
||||
==== excessPropertyCheckingInArrayDestructuring.ts (2 errors) ====
|
||||
declare function foo<T extends { dataType: 'a' | 'b' }>(template: T): [T, any, any];
|
||||
declare function bar<T extends { dataType: 'a' | 'b' }>(template: T): [any, T, any];
|
||||
|
||||
// Test cases that should work (no excess property errors)
|
||||
const [, works1] = foo({ dataType: 'a', day: 0 });
|
||||
const [, , works2] = foo({ dataType: 'a', day: 0 });
|
||||
const [, , , works3] = foo({ dataType: 'a', day: 0 });
|
||||
~~~~~~
|
||||
!!! error TS2493: Tuple type '[{ dataType: "a"; day: number; }, any, any]' of length '3' has no element at index '3'.
|
||||
// Test the specific problematic case that should now work
|
||||
const [, , works1] = foo({ dataType: 'a', day: 0 });
|
||||
const [, , works2] = foo({ dataType: 'b', extra: 'value' });
|
||||
|
||||
// Test with different function signatures
|
||||
const [, , works4] = bar({ dataType: 'b', extra: 'value' });
|
||||
|
||||
// Test assignment destructuring
|
||||
let a: any, b: any, c: any;
|
||||
[, , a] = foo({ dataType: 'a', day: 0 });
|
||||
[, b, ] = foo({ dataType: 'a', day: 0 });
|
||||
// Test assignment destructuring (not currently fixed)
|
||||
let a: any;
|
||||
[, , a] = foo({ dataType: 'a', day: 0 }); // This might still error
|
||||
|
||||
// Test that legitimate errors are still caught
|
||||
const [, , fails1] = foo({ dataType: 'c' }); // Error: 'c' not assignable to 'a' | 'b'
|
||||
@ -33,4 +24,8 @@ excessPropertyCheckingInArrayDestructuring.ts(19,26): error TS2345: Argument of
|
||||
|
||||
// Test that non-destructuring cases work as before
|
||||
const result = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
const explicit: [{ dataType: 'a', day: number }, any, any] = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
const explicit: [{ dataType: 'a', day: number }, any, any] = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
|
||||
// Test that other destructuring patterns work correctly
|
||||
const [first] = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
const [, second] = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
@ -2,20 +2,14 @@
|
||||
|
||||
//// [excessPropertyCheckingInArrayDestructuring.ts]
|
||||
declare function foo<T extends { dataType: 'a' | 'b' }>(template: T): [T, any, any];
|
||||
declare function bar<T extends { dataType: 'a' | 'b' }>(template: T): [any, T, any];
|
||||
|
||||
// Test cases that should work (no excess property errors)
|
||||
const [, works1] = foo({ dataType: 'a', day: 0 });
|
||||
const [, , works2] = foo({ dataType: 'a', day: 0 });
|
||||
const [, , , works3] = foo({ dataType: 'a', day: 0 });
|
||||
// Test the specific problematic case that should now work
|
||||
const [, , works1] = foo({ dataType: 'a', day: 0 });
|
||||
const [, , works2] = foo({ dataType: 'b', extra: 'value' });
|
||||
|
||||
// Test with different function signatures
|
||||
const [, , works4] = bar({ dataType: 'b', extra: 'value' });
|
||||
|
||||
// Test assignment destructuring
|
||||
let a: any, b: any, c: any;
|
||||
[, , a] = foo({ dataType: 'a', day: 0 });
|
||||
[, b, ] = foo({ dataType: 'a', day: 0 });
|
||||
// Test assignment destructuring (not currently fixed)
|
||||
let a: any;
|
||||
[, , a] = foo({ dataType: 'a', day: 0 }); // This might still error
|
||||
|
||||
// Test that legitimate errors are still caught
|
||||
const [, , fails1] = foo({ dataType: 'c' }); // Error: 'c' not assignable to 'a' | 'b'
|
||||
@ -23,24 +17,27 @@ const [, , fails2] = foo(123); // Error: number not assignable to constraint
|
||||
|
||||
// Test that non-destructuring cases work as before
|
||||
const result = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
const explicit: [{ dataType: 'a', day: number }, any, any] = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
const explicit: [{ dataType: 'a', day: number }, any, any] = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
|
||||
// Test that other destructuring patterns work correctly
|
||||
const [first] = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
const [, second] = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
|
||||
//// [excessPropertyCheckingInArrayDestructuring.js]
|
||||
"use strict";
|
||||
var _a, _b;
|
||||
// Test cases that should work (no excess property errors)
|
||||
var _c = foo({ dataType: 'a', day: 0 }), works1 = _c[1];
|
||||
var _d = foo({ dataType: 'a', day: 0 }), works2 = _d[2];
|
||||
var _e = foo({ dataType: 'a', day: 0 }), works3 = _e[3];
|
||||
// Test with different function signatures
|
||||
var _f = bar({ dataType: 'b', extra: 'value' }), works4 = _f[2];
|
||||
// Test assignment destructuring
|
||||
var a, b, c;
|
||||
_a = foo({ dataType: 'a', day: 0 }), a = _a[2];
|
||||
_b = foo({ dataType: 'a', day: 0 }), b = _b[1];
|
||||
var _a;
|
||||
// Test the specific problematic case that should now work
|
||||
var _b = foo({ dataType: 'a', day: 0 }), works1 = _b[2];
|
||||
var _c = foo({ dataType: 'b', extra: 'value' }), works2 = _c[2];
|
||||
// Test assignment destructuring (not currently fixed)
|
||||
var a;
|
||||
_a = foo({ dataType: 'a', day: 0 }), a = _a[2]; // This might still error
|
||||
// Test that legitimate errors are still caught
|
||||
var _g = foo({ dataType: 'c' }), fails1 = _g[2]; // Error: 'c' not assignable to 'a' | 'b'
|
||||
var _h = foo(123), fails2 = _h[2]; // Error: number not assignable to constraint
|
||||
var _d = foo({ dataType: 'c' }), fails1 = _d[2]; // Error: 'c' not assignable to 'a' | 'b'
|
||||
var _e = foo(123), fails2 = _e[2]; // Error: number not assignable to constraint
|
||||
// Test that non-destructuring cases work as before
|
||||
var result = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
var explicit = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
// Test that other destructuring patterns work correctly
|
||||
var first = foo({ dataType: 'a', day: 0 })[0]; // Should work
|
||||
var _f = foo({ dataType: 'a', day: 0 }), second = _f[1]; // Should work
|
||||
|
||||
@ -9,80 +9,64 @@ declare function foo<T extends { dataType: 'a' | 'b' }>(template: T): [T, any, a
|
||||
>T : Symbol(T, Decl(excessPropertyCheckingInArrayDestructuring.ts, 0, 21))
|
||||
>T : Symbol(T, Decl(excessPropertyCheckingInArrayDestructuring.ts, 0, 21))
|
||||
|
||||
declare function bar<T extends { dataType: 'a' | 'b' }>(template: T): [any, T, any];
|
||||
>bar : Symbol(bar, Decl(excessPropertyCheckingInArrayDestructuring.ts, 0, 84))
|
||||
>T : Symbol(T, Decl(excessPropertyCheckingInArrayDestructuring.ts, 1, 21))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 1, 32))
|
||||
>template : Symbol(template, Decl(excessPropertyCheckingInArrayDestructuring.ts, 1, 56))
|
||||
>T : Symbol(T, Decl(excessPropertyCheckingInArrayDestructuring.ts, 1, 21))
|
||||
>T : Symbol(T, Decl(excessPropertyCheckingInArrayDestructuring.ts, 1, 21))
|
||||
|
||||
// Test cases that should work (no excess property errors)
|
||||
const [, works1] = foo({ dataType: 'a', day: 0 });
|
||||
>works1 : Symbol(works1, Decl(excessPropertyCheckingInArrayDestructuring.ts, 4, 8))
|
||||
// Test the specific problematic case that should now work
|
||||
const [, , works1] = foo({ dataType: 'a', day: 0 });
|
||||
>works1 : Symbol(works1, Decl(excessPropertyCheckingInArrayDestructuring.ts, 3, 10))
|
||||
>foo : Symbol(foo, Decl(excessPropertyCheckingInArrayDestructuring.ts, 0, 0))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 4, 24))
|
||||
>day : Symbol(day, Decl(excessPropertyCheckingInArrayDestructuring.ts, 4, 39))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 3, 26))
|
||||
>day : Symbol(day, Decl(excessPropertyCheckingInArrayDestructuring.ts, 3, 41))
|
||||
|
||||
const [, , works2] = foo({ dataType: 'a', day: 0 });
|
||||
>works2 : Symbol(works2, Decl(excessPropertyCheckingInArrayDestructuring.ts, 5, 10))
|
||||
const [, , works2] = foo({ dataType: 'b', extra: 'value' });
|
||||
>works2 : Symbol(works2, Decl(excessPropertyCheckingInArrayDestructuring.ts, 4, 10))
|
||||
>foo : Symbol(foo, Decl(excessPropertyCheckingInArrayDestructuring.ts, 0, 0))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 5, 26))
|
||||
>day : Symbol(day, Decl(excessPropertyCheckingInArrayDestructuring.ts, 5, 41))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 4, 26))
|
||||
>extra : Symbol(extra, Decl(excessPropertyCheckingInArrayDestructuring.ts, 4, 41))
|
||||
|
||||
const [, , , works3] = foo({ dataType: 'a', day: 0 });
|
||||
>works3 : Symbol(works3, Decl(excessPropertyCheckingInArrayDestructuring.ts, 6, 12))
|
||||
// Test assignment destructuring (not currently fixed)
|
||||
let a: any;
|
||||
>a : Symbol(a, Decl(excessPropertyCheckingInArrayDestructuring.ts, 7, 3))
|
||||
|
||||
[, , a] = foo({ dataType: 'a', day: 0 }); // This might still error
|
||||
>a : Symbol(a, Decl(excessPropertyCheckingInArrayDestructuring.ts, 7, 3))
|
||||
>foo : Symbol(foo, Decl(excessPropertyCheckingInArrayDestructuring.ts, 0, 0))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 6, 28))
|
||||
>day : Symbol(day, Decl(excessPropertyCheckingInArrayDestructuring.ts, 6, 43))
|
||||
|
||||
// Test with different function signatures
|
||||
const [, , works4] = bar({ dataType: 'b', extra: 'value' });
|
||||
>works4 : Symbol(works4, Decl(excessPropertyCheckingInArrayDestructuring.ts, 9, 10))
|
||||
>bar : Symbol(bar, Decl(excessPropertyCheckingInArrayDestructuring.ts, 0, 84))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 9, 26))
|
||||
>extra : Symbol(extra, Decl(excessPropertyCheckingInArrayDestructuring.ts, 9, 41))
|
||||
|
||||
// Test assignment destructuring
|
||||
let a: any, b: any, c: any;
|
||||
>a : Symbol(a, Decl(excessPropertyCheckingInArrayDestructuring.ts, 12, 3))
|
||||
>b : Symbol(b, Decl(excessPropertyCheckingInArrayDestructuring.ts, 12, 11))
|
||||
>c : Symbol(c, Decl(excessPropertyCheckingInArrayDestructuring.ts, 12, 19))
|
||||
|
||||
[, , a] = foo({ dataType: 'a', day: 0 });
|
||||
>a : Symbol(a, Decl(excessPropertyCheckingInArrayDestructuring.ts, 12, 3))
|
||||
>foo : Symbol(foo, Decl(excessPropertyCheckingInArrayDestructuring.ts, 0, 0))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 13, 15))
|
||||
>day : Symbol(day, Decl(excessPropertyCheckingInArrayDestructuring.ts, 13, 30))
|
||||
|
||||
[, b, ] = foo({ dataType: 'a', day: 0 });
|
||||
>b : Symbol(b, Decl(excessPropertyCheckingInArrayDestructuring.ts, 12, 11))
|
||||
>foo : Symbol(foo, Decl(excessPropertyCheckingInArrayDestructuring.ts, 0, 0))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 14, 15))
|
||||
>day : Symbol(day, Decl(excessPropertyCheckingInArrayDestructuring.ts, 14, 30))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 8, 15))
|
||||
>day : Symbol(day, Decl(excessPropertyCheckingInArrayDestructuring.ts, 8, 30))
|
||||
|
||||
// Test that legitimate errors are still caught
|
||||
const [, , fails1] = foo({ dataType: 'c' }); // Error: 'c' not assignable to 'a' | 'b'
|
||||
>fails1 : Symbol(fails1, Decl(excessPropertyCheckingInArrayDestructuring.ts, 17, 10))
|
||||
>fails1 : Symbol(fails1, Decl(excessPropertyCheckingInArrayDestructuring.ts, 11, 10))
|
||||
>foo : Symbol(foo, Decl(excessPropertyCheckingInArrayDestructuring.ts, 0, 0))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 17, 26))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 11, 26))
|
||||
|
||||
const [, , fails2] = foo(123); // Error: number not assignable to constraint
|
||||
>fails2 : Symbol(fails2, Decl(excessPropertyCheckingInArrayDestructuring.ts, 18, 10))
|
||||
>fails2 : Symbol(fails2, Decl(excessPropertyCheckingInArrayDestructuring.ts, 12, 10))
|
||||
>foo : Symbol(foo, Decl(excessPropertyCheckingInArrayDestructuring.ts, 0, 0))
|
||||
|
||||
// Test that non-destructuring cases work as before
|
||||
const result = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
>result : Symbol(result, Decl(excessPropertyCheckingInArrayDestructuring.ts, 21, 5))
|
||||
>result : Symbol(result, Decl(excessPropertyCheckingInArrayDestructuring.ts, 15, 5))
|
||||
>foo : Symbol(foo, Decl(excessPropertyCheckingInArrayDestructuring.ts, 0, 0))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 21, 20))
|
||||
>day : Symbol(day, Decl(excessPropertyCheckingInArrayDestructuring.ts, 21, 35))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 15, 20))
|
||||
>day : Symbol(day, Decl(excessPropertyCheckingInArrayDestructuring.ts, 15, 35))
|
||||
|
||||
const explicit: [{ dataType: 'a', day: number }, any, any] = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
>explicit : Symbol(explicit, Decl(excessPropertyCheckingInArrayDestructuring.ts, 22, 5))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 22, 18))
|
||||
>day : Symbol(day, Decl(excessPropertyCheckingInArrayDestructuring.ts, 22, 33))
|
||||
>explicit : Symbol(explicit, Decl(excessPropertyCheckingInArrayDestructuring.ts, 16, 5))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 16, 18))
|
||||
>day : Symbol(day, Decl(excessPropertyCheckingInArrayDestructuring.ts, 16, 33))
|
||||
>foo : Symbol(foo, Decl(excessPropertyCheckingInArrayDestructuring.ts, 0, 0))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 22, 66))
|
||||
>day : Symbol(day, Decl(excessPropertyCheckingInArrayDestructuring.ts, 22, 81))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 16, 66))
|
||||
>day : Symbol(day, Decl(excessPropertyCheckingInArrayDestructuring.ts, 16, 81))
|
||||
|
||||
// Test that other destructuring patterns work correctly
|
||||
const [first] = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
>first : Symbol(first, Decl(excessPropertyCheckingInArrayDestructuring.ts, 19, 7))
|
||||
>foo : Symbol(foo, Decl(excessPropertyCheckingInArrayDestructuring.ts, 0, 0))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 19, 21))
|
||||
>day : Symbol(day, Decl(excessPropertyCheckingInArrayDestructuring.ts, 19, 36))
|
||||
|
||||
const [, second] = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
>second : Symbol(second, Decl(excessPropertyCheckingInArrayDestructuring.ts, 20, 8))
|
||||
>foo : Symbol(foo, Decl(excessPropertyCheckingInArrayDestructuring.ts, 0, 0))
|
||||
>dataType : Symbol(dataType, Decl(excessPropertyCheckingInArrayDestructuring.ts, 20, 24))
|
||||
>day : Symbol(day, Decl(excessPropertyCheckingInArrayDestructuring.ts, 20, 39))
|
||||
|
||||
|
||||
@ -9,42 +9,14 @@ declare function foo<T extends { dataType: 'a' | 'b' }>(template: T): [T, any, a
|
||||
>template : T
|
||||
> : ^
|
||||
|
||||
declare function bar<T extends { dataType: 'a' | 'b' }>(template: T): [any, T, any];
|
||||
>bar : <T extends { dataType: "a" | "b"; }>(template: T) => [any, T, any]
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>dataType : "a" | "b"
|
||||
> : ^^^^^^^^^
|
||||
>template : T
|
||||
> : ^
|
||||
|
||||
// Test cases that should work (no excess property errors)
|
||||
const [, works1] = foo({ dataType: 'a', day: 0 });
|
||||
// Test the specific problematic case that should now work
|
||||
const [, , works1] = foo({ dataType: 'a', day: 0 });
|
||||
> : undefined
|
||||
> : ^^^^^^^^^
|
||||
> : undefined
|
||||
> : ^^^^^^^^^
|
||||
>works1 : any
|
||||
> : ^^^
|
||||
>foo({ dataType: 'a', day: 0 }) : [{ dataType: "a"; day: number; }, any, any]
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>foo : <T extends { dataType: "a" | "b"; }>(template: T) => [T, any, any]
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>{ dataType: 'a', day: 0 } : { dataType: "a"; day: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>dataType : "a"
|
||||
> : ^^^
|
||||
>'a' : "a"
|
||||
> : ^^^
|
||||
>day : number
|
||||
> : ^^^^^^
|
||||
>0 : 0
|
||||
> : ^
|
||||
|
||||
const [, , works2] = foo({ dataType: 'a', day: 0 });
|
||||
> : undefined
|
||||
> : ^^^^^^^^^
|
||||
> : undefined
|
||||
> : ^^^^^^^^^
|
||||
>works2 : any
|
||||
> : ^^^
|
||||
>foo({ dataType: 'a', day: 0 }) : [{ dataType: "a" | "b"; }, any, any]
|
||||
> : ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
|
||||
>foo : <T extends { dataType: "a" | "b"; }>(template: T) => [T, any, any]
|
||||
@ -60,41 +32,16 @@ const [, , works2] = foo({ dataType: 'a', day: 0 });
|
||||
>0 : 0
|
||||
> : ^
|
||||
|
||||
const [, , , works3] = foo({ dataType: 'a', day: 0 });
|
||||
const [, , works2] = foo({ dataType: 'b', extra: 'value' });
|
||||
> : undefined
|
||||
> : ^^^^^^^^^
|
||||
> : undefined
|
||||
> : ^^^^^^^^^
|
||||
> : undefined
|
||||
> : ^^^^^^^^^
|
||||
>works3 : undefined
|
||||
> : ^^^^^^^^^
|
||||
>foo({ dataType: 'a', day: 0 }) : [{ dataType: "a"; day: number; }, any, any]
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>foo : <T extends { dataType: "a" | "b"; }>(template: T) => [T, any, any]
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>{ dataType: 'a', day: 0 } : { dataType: "a"; day: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>dataType : "a"
|
||||
> : ^^^
|
||||
>'a' : "a"
|
||||
> : ^^^
|
||||
>day : number
|
||||
> : ^^^^^^
|
||||
>0 : 0
|
||||
> : ^
|
||||
|
||||
// Test with different function signatures
|
||||
const [, , works4] = bar({ dataType: 'b', extra: 'value' });
|
||||
> : undefined
|
||||
> : ^^^^^^^^^
|
||||
> : undefined
|
||||
> : ^^^^^^^^^
|
||||
>works4 : any
|
||||
>works2 : any
|
||||
> : ^^^
|
||||
>bar({ dataType: 'b', extra: 'value' }) : [any, { dataType: "a" | "b"; }, any]
|
||||
> : ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^
|
||||
>bar : <T extends { dataType: "a" | "b"; }>(template: T) => [any, T, any]
|
||||
>foo({ dataType: 'b', extra: 'value' }) : [{ dataType: "a" | "b"; }, any, any]
|
||||
> : ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
|
||||
>foo : <T extends { dataType: "a" | "b"; }>(template: T) => [T, any, any]
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>{ dataType: 'b', extra: 'value' } : { dataType: "b"; extra: string; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -107,16 +54,12 @@ const [, , works4] = bar({ dataType: 'b', extra: 'value' });
|
||||
>'value' : "value"
|
||||
> : ^^^^^^^
|
||||
|
||||
// Test assignment destructuring
|
||||
let a: any, b: any, c: any;
|
||||
// Test assignment destructuring (not currently fixed)
|
||||
let a: any;
|
||||
>a : any
|
||||
> : ^^^
|
||||
>b : any
|
||||
> : ^^^
|
||||
>c : any
|
||||
> : ^^^
|
||||
|
||||
[, , a] = foo({ dataType: 'a', day: 0 });
|
||||
[, , a] = foo({ dataType: 'a', day: 0 }); // This might still error
|
||||
>[, , a] = foo({ dataType: 'a', day: 0 }) : [{ dataType: "a"; day: number; }, any, any]
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>[, , a] : [undefined, undefined, any]
|
||||
@ -142,30 +85,6 @@ let a: any, b: any, c: any;
|
||||
>0 : 0
|
||||
> : ^
|
||||
|
||||
[, b, ] = foo({ dataType: 'a', day: 0 });
|
||||
>[, b, ] = foo({ dataType: 'a', day: 0 }) : [{ dataType: "a"; day: number; }, any, any]
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>[, b, ] : [undefined, any]
|
||||
> : ^^^^^^^^^^^^^^^^
|
||||
> : undefined
|
||||
> : ^^^^^^^^^
|
||||
>b : any
|
||||
> : ^^^
|
||||
>foo({ dataType: 'a', day: 0 }) : [{ dataType: "a"; day: number; }, any, any]
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>foo : <T extends { dataType: "a" | "b"; }>(template: T) => [T, any, any]
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>{ dataType: 'a', day: 0 } : { dataType: "a"; day: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>dataType : "a"
|
||||
> : ^^^
|
||||
>'a' : "a"
|
||||
> : ^^^
|
||||
>day : number
|
||||
> : ^^^^^^
|
||||
>0 : 0
|
||||
> : ^
|
||||
|
||||
// Test that legitimate errors are still caught
|
||||
const [, , fails1] = foo({ dataType: 'c' }); // Error: 'c' not assignable to 'a' | 'b'
|
||||
> : undefined
|
||||
@ -240,3 +159,42 @@ const explicit: [{ dataType: 'a', day: number }, any, any] = foo({ dataType: 'a'
|
||||
>0 : 0
|
||||
> : ^
|
||||
|
||||
// Test that other destructuring patterns work correctly
|
||||
const [first] = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
>first : { dataType: "a"; day: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>foo({ dataType: 'a', day: 0 }) : [{ dataType: "a"; day: number; }, any, any]
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>foo : <T extends { dataType: "a" | "b"; }>(template: T) => [T, any, any]
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>{ dataType: 'a', day: 0 } : { dataType: "a"; day: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>dataType : "a"
|
||||
> : ^^^
|
||||
>'a' : "a"
|
||||
> : ^^^
|
||||
>day : number
|
||||
> : ^^^^^^
|
||||
>0 : 0
|
||||
> : ^
|
||||
|
||||
const [, second] = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
> : undefined
|
||||
> : ^^^^^^^^^
|
||||
>second : any
|
||||
> : ^^^
|
||||
>foo({ dataType: 'a', day: 0 }) : [{ dataType: "a"; day: number; }, any, any]
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>foo : <T extends { dataType: "a" | "b"; }>(template: T) => [T, any, any]
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>{ dataType: 'a', day: 0 } : { dataType: "a"; day: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>dataType : "a"
|
||||
> : ^^^
|
||||
>'a' : "a"
|
||||
> : ^^^
|
||||
>day : number
|
||||
> : ^^^^^^
|
||||
>0 : 0
|
||||
> : ^
|
||||
|
||||
|
||||
@ -1,20 +1,14 @@
|
||||
// @strict: true
|
||||
|
||||
declare function foo<T extends { dataType: 'a' | 'b' }>(template: T): [T, any, any];
|
||||
declare function bar<T extends { dataType: 'a' | 'b' }>(template: T): [any, T, any];
|
||||
|
||||
// Test cases that should work (no excess property errors)
|
||||
const [, works1] = foo({ dataType: 'a', day: 0 });
|
||||
const [, , works2] = foo({ dataType: 'a', day: 0 });
|
||||
const [, , , works3] = foo({ dataType: 'a', day: 0 });
|
||||
// Test the specific problematic case that should now work
|
||||
const [, , works1] = foo({ dataType: 'a', day: 0 });
|
||||
const [, , works2] = foo({ dataType: 'b', extra: 'value' });
|
||||
|
||||
// Test with different function signatures
|
||||
const [, , works4] = bar({ dataType: 'b', extra: 'value' });
|
||||
|
||||
// Test assignment destructuring
|
||||
let a: any, b: any, c: any;
|
||||
[, , a] = foo({ dataType: 'a', day: 0 });
|
||||
[, b, ] = foo({ dataType: 'a', day: 0 });
|
||||
// Test assignment destructuring (not currently fixed)
|
||||
let a: any;
|
||||
[, , a] = foo({ dataType: 'a', day: 0 }); // This might still error
|
||||
|
||||
// Test that legitimate errors are still caught
|
||||
const [, , fails1] = foo({ dataType: 'c' }); // Error: 'c' not assignable to 'a' | 'b'
|
||||
@ -22,4 +16,8 @@ const [, , fails2] = foo(123); // Error: number not assignable to constraint
|
||||
|
||||
// Test that non-destructuring cases work as before
|
||||
const result = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
const explicit: [{ dataType: 'a', day: number }, any, any] = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
const explicit: [{ dataType: 'a', day: number }, any, any] = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
|
||||
// Test that other destructuring patterns work correctly
|
||||
const [first] = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
const [, second] = foo({ dataType: 'a', day: 0 }); // Should work
|
||||
Loading…
x
Reference in New Issue
Block a user