diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3192b392a1b..77f35376da7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22901,47 +22901,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ) { return false; } - - // Heuristic: If the target type looks like a constraint (simple object type with few properties), - // be more lenient with excess property checking. This handles cases like T extends { prop: Type } - // where the constraint should allow additional properties. - if (target.flags & TypeFlags.Object && !isComparingJsxAttributes) { - const targetProperties = getPropertiesOfType(target); - const targetIndexInfos = getIndexInfosOfType(target); - // If it's a simple object with few properties and no index signatures, it might be a constraint - if (targetProperties.length <= 2 && targetIndexInfos.length === 0) { - // Additional check: at least one property should be a simple string literal union (common in constraints) - // This helps distinguish constraints like { dataType: 'a' | 'b' } from complex intersection types - let hasSimpleUnionProperty = false; - for (const targetProp of targetProperties) { - const propType = getTypeOfSymbol(targetProp); - if (propType.flags & TypeFlags.Union) { - const unionType = propType as UnionType; - // Check if it's a union of string literals (typical of enum-like constraints) - if (unionType.types.length <= 5 && unionType.types.every(t => t.flags & TypeFlags.StringLiteral)) { - hasSimpleUnionProperty = true; - break; - } - } - } - - if (hasSimpleUnionProperty) { - // Check if all properties in the target exist in the source - let allTargetPropsExist = true; - for (const targetProp of targetProperties) { - if (!source.symbol?.members?.has(targetProp.escapedName)) { - allTargetPropsExist = false; - break; - } - } - // If the source contains all target properties, likely this is a constraint scenario - if (allTargetPropsExist) { - return false; - } - } - } - } - let reducedTarget = target; let checkTypes: Type[] | undefined; if (target.flags & TypeFlags.Union) { @@ -34322,10 +34281,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (targetType.flags & TypeFlags.Substitution) { return isKnownProperty((targetType as SubstitutionType).baseType, name, isComparingJsxAttributes); } - if (targetType.flags & TypeFlags.TypeParameter) { - const constraint = getConstraintOfTypeParameter(targetType as TypeParameter); - return constraint ? isKnownProperty(constraint, name, isComparingJsxAttributes) : false; - } if (targetType.flags & TypeFlags.UnionOrIntersection && isExcessPropertyCheckTarget(targetType)) { for (const t of (targetType as UnionOrIntersectionType).types) { if (isKnownProperty(t, name, isComparingJsxAttributes)) { diff --git a/tests/baselines/reference/destructuringAssignmentWithConstraints.js b/tests/baselines/reference/destructuringAssignmentWithConstraints.js deleted file mode 100644 index 1f73e4750ec..00000000000 --- a/tests/baselines/reference/destructuringAssignmentWithConstraints.js +++ /dev/null @@ -1,50 +0,0 @@ -//// [tests/cases/compiler/destructuringAssignmentWithConstraints.ts] //// - -//// [destructuringAssignmentWithConstraints.ts] -// Test case for destructuring assignment with generic constraints issue - -type DataType = 'a' | 'b'; - -declare function foo(template: T): [T, any, any]; -declare function bar(template: T): [T, any]; - -function testDestructuringBug() { - // These work fine (and should continue to work) - const [, ,] = foo({ dataType: 'a', day: 0 }); - const [x, y, z] = foo({ dataType: 'a', day: 0 }); - const [,] = bar({ dataType: 'a', day: 0 }); - const [a, b] = bar({ dataType: 'a', day: 0 }); - - // These should work but currently don't (this is the bug) - const [, , t] = foo({ dataType: 'a', day: 0 }); // Should not error - const [, u] = bar({ dataType: 'a', day: 0 }); // Should not error - - console.log(x, y, z, t, a, b, u); -} - -// Test that direct calls work fine (they do) -function testDirectCalls() { - const result1 = foo({ dataType: 'a', day: 0 }); - const result2 = bar({ dataType: 'a', day: 0 }); - console.log(result1, result2); -} - -//// [destructuringAssignmentWithConstraints.js] -// Test case for destructuring assignment with generic constraints issue -function testDestructuringBug() { - // These work fine (and should continue to work) - var _a = foo({ dataType: 'a', day: 0 }); - var _b = foo({ dataType: 'a', day: 0 }), x = _b[0], y = _b[1], z = _b[2]; - var _c = bar({ dataType: 'a', day: 0 }); - var _d = bar({ dataType: 'a', day: 0 }), a = _d[0], b = _d[1]; - // These should work but currently don't (this is the bug) - var _e = foo({ dataType: 'a', day: 0 }), t = _e[2]; // Should not error - var _f = bar({ dataType: 'a', day: 0 }), u = _f[1]; // Should not error - console.log(x, y, z, t, a, b, u); -} -// Test that direct calls work fine (they do) -function testDirectCalls() { - var result1 = foo({ dataType: 'a', day: 0 }); - var result2 = bar({ dataType: 'a', day: 0 }); - console.log(result1, result2); -} diff --git a/tests/baselines/reference/destructuringAssignmentWithConstraints.symbols b/tests/baselines/reference/destructuringAssignmentWithConstraints.symbols deleted file mode 100644 index 18eb42dbf89..00000000000 --- a/tests/baselines/reference/destructuringAssignmentWithConstraints.symbols +++ /dev/null @@ -1,104 +0,0 @@ -//// [tests/cases/compiler/destructuringAssignmentWithConstraints.ts] //// - -=== destructuringAssignmentWithConstraints.ts === -// Test case for destructuring assignment with generic constraints issue - -type DataType = 'a' | 'b'; ->DataType : Symbol(DataType, Decl(destructuringAssignmentWithConstraints.ts, 0, 0)) - -declare function foo(template: T): [T, any, any]; ->foo : Symbol(foo, Decl(destructuringAssignmentWithConstraints.ts, 2, 26)) ->T : Symbol(T, Decl(destructuringAssignmentWithConstraints.ts, 4, 21)) ->dataType : Symbol(dataType, Decl(destructuringAssignmentWithConstraints.ts, 4, 32)) ->DataType : Symbol(DataType, Decl(destructuringAssignmentWithConstraints.ts, 0, 0)) ->template : Symbol(template, Decl(destructuringAssignmentWithConstraints.ts, 4, 55)) ->T : Symbol(T, Decl(destructuringAssignmentWithConstraints.ts, 4, 21)) ->T : Symbol(T, Decl(destructuringAssignmentWithConstraints.ts, 4, 21)) - -declare function bar(template: T): [T, any]; ->bar : Symbol(bar, Decl(destructuringAssignmentWithConstraints.ts, 4, 83)) ->T : Symbol(T, Decl(destructuringAssignmentWithConstraints.ts, 5, 21)) ->dataType : Symbol(dataType, Decl(destructuringAssignmentWithConstraints.ts, 5, 32)) ->DataType : Symbol(DataType, Decl(destructuringAssignmentWithConstraints.ts, 0, 0)) ->template : Symbol(template, Decl(destructuringAssignmentWithConstraints.ts, 5, 55)) ->T : Symbol(T, Decl(destructuringAssignmentWithConstraints.ts, 5, 21)) ->T : Symbol(T, Decl(destructuringAssignmentWithConstraints.ts, 5, 21)) - -function testDestructuringBug() { ->testDestructuringBug : Symbol(testDestructuringBug, Decl(destructuringAssignmentWithConstraints.ts, 5, 78)) - - // These work fine (and should continue to work) - const [, ,] = foo({ dataType: 'a', day: 0 }); ->foo : Symbol(foo, Decl(destructuringAssignmentWithConstraints.ts, 2, 26)) ->dataType : Symbol(dataType, Decl(destructuringAssignmentWithConstraints.ts, 9, 21)) ->day : Symbol(day, Decl(destructuringAssignmentWithConstraints.ts, 9, 36)) - - const [x, y, z] = foo({ dataType: 'a', day: 0 }); ->x : Symbol(x, Decl(destructuringAssignmentWithConstraints.ts, 10, 9)) ->y : Symbol(y, Decl(destructuringAssignmentWithConstraints.ts, 10, 11)) ->z : Symbol(z, Decl(destructuringAssignmentWithConstraints.ts, 10, 14)) ->foo : Symbol(foo, Decl(destructuringAssignmentWithConstraints.ts, 2, 26)) ->dataType : Symbol(dataType, Decl(destructuringAssignmentWithConstraints.ts, 10, 25)) ->day : Symbol(day, Decl(destructuringAssignmentWithConstraints.ts, 10, 40)) - - const [,] = bar({ dataType: 'a', day: 0 }); ->bar : Symbol(bar, Decl(destructuringAssignmentWithConstraints.ts, 4, 83)) ->dataType : Symbol(dataType, Decl(destructuringAssignmentWithConstraints.ts, 11, 19)) ->day : Symbol(day, Decl(destructuringAssignmentWithConstraints.ts, 11, 34)) - - const [a, b] = bar({ dataType: 'a', day: 0 }); ->a : Symbol(a, Decl(destructuringAssignmentWithConstraints.ts, 12, 9)) ->b : Symbol(b, Decl(destructuringAssignmentWithConstraints.ts, 12, 11)) ->bar : Symbol(bar, Decl(destructuringAssignmentWithConstraints.ts, 4, 83)) ->dataType : Symbol(dataType, Decl(destructuringAssignmentWithConstraints.ts, 12, 22)) ->day : Symbol(day, Decl(destructuringAssignmentWithConstraints.ts, 12, 37)) - - // These should work but currently don't (this is the bug) - const [, , t] = foo({ dataType: 'a', day: 0 }); // Should not error ->t : Symbol(t, Decl(destructuringAssignmentWithConstraints.ts, 15, 12)) ->foo : Symbol(foo, Decl(destructuringAssignmentWithConstraints.ts, 2, 26)) ->dataType : Symbol(dataType, Decl(destructuringAssignmentWithConstraints.ts, 15, 23)) ->day : Symbol(day, Decl(destructuringAssignmentWithConstraints.ts, 15, 38)) - - const [, u] = bar({ dataType: 'a', day: 0 }); // Should not error ->u : Symbol(u, Decl(destructuringAssignmentWithConstraints.ts, 16, 10)) ->bar : Symbol(bar, Decl(destructuringAssignmentWithConstraints.ts, 4, 83)) ->dataType : Symbol(dataType, Decl(destructuringAssignmentWithConstraints.ts, 16, 21)) ->day : Symbol(day, Decl(destructuringAssignmentWithConstraints.ts, 16, 36)) - - console.log(x, y, z, t, a, b, u); ->console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->console : Symbol(console, Decl(lib.dom.d.ts, --, --)) ->log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->x : Symbol(x, Decl(destructuringAssignmentWithConstraints.ts, 10, 9)) ->y : Symbol(y, Decl(destructuringAssignmentWithConstraints.ts, 10, 11)) ->z : Symbol(z, Decl(destructuringAssignmentWithConstraints.ts, 10, 14)) ->t : Symbol(t, Decl(destructuringAssignmentWithConstraints.ts, 15, 12)) ->a : Symbol(a, Decl(destructuringAssignmentWithConstraints.ts, 12, 9)) ->b : Symbol(b, Decl(destructuringAssignmentWithConstraints.ts, 12, 11)) ->u : Symbol(u, Decl(destructuringAssignmentWithConstraints.ts, 16, 10)) -} - -// Test that direct calls work fine (they do) -function testDirectCalls() { ->testDirectCalls : Symbol(testDirectCalls, Decl(destructuringAssignmentWithConstraints.ts, 19, 1)) - - const result1 = foo({ dataType: 'a', day: 0 }); ->result1 : Symbol(result1, Decl(destructuringAssignmentWithConstraints.ts, 23, 7)) ->foo : Symbol(foo, Decl(destructuringAssignmentWithConstraints.ts, 2, 26)) ->dataType : Symbol(dataType, Decl(destructuringAssignmentWithConstraints.ts, 23, 23)) ->day : Symbol(day, Decl(destructuringAssignmentWithConstraints.ts, 23, 38)) - - const result2 = bar({ dataType: 'a', day: 0 }); ->result2 : Symbol(result2, Decl(destructuringAssignmentWithConstraints.ts, 24, 7)) ->bar : Symbol(bar, Decl(destructuringAssignmentWithConstraints.ts, 4, 83)) ->dataType : Symbol(dataType, Decl(destructuringAssignmentWithConstraints.ts, 24, 23)) ->day : Symbol(day, Decl(destructuringAssignmentWithConstraints.ts, 24, 38)) - - console.log(result1, result2); ->console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->console : Symbol(console, Decl(lib.dom.d.ts, --, --)) ->log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->result1 : Symbol(result1, Decl(destructuringAssignmentWithConstraints.ts, 23, 7)) ->result2 : Symbol(result2, Decl(destructuringAssignmentWithConstraints.ts, 24, 7)) -} diff --git a/tests/baselines/reference/destructuringAssignmentWithConstraints.types b/tests/baselines/reference/destructuringAssignmentWithConstraints.types deleted file mode 100644 index 5a2daba7cb5..00000000000 --- a/tests/baselines/reference/destructuringAssignmentWithConstraints.types +++ /dev/null @@ -1,228 +0,0 @@ -//// [tests/cases/compiler/destructuringAssignmentWithConstraints.ts] //// - -=== destructuringAssignmentWithConstraints.ts === -// Test case for destructuring assignment with generic constraints issue - -type DataType = 'a' | 'b'; ->DataType : DataType -> : ^^^^^^^^ - -declare function foo(template: T): [T, any, any]; ->foo : (template: T) => [T, any, any] -> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ ->dataType : DataType -> : ^^^^^^^^ ->template : T -> : ^ - -declare function bar(template: T): [T, any]; ->bar : (template: T) => [T, any] -> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ ->dataType : DataType -> : ^^^^^^^^ ->template : T -> : ^ - -function testDestructuringBug() { ->testDestructuringBug : () => void -> : ^^^^^^^^^^ - - // These work fine (and should continue to work) - const [, ,] = foo({ dataType: 'a', day: 0 }); -> : undefined -> : ^^^^^^^^^ -> : undefined -> : ^^^^^^^^^ ->foo({ dataType: 'a', day: 0 }) : [{ dataType: "a"; day: number; }, any, any] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->foo : (template: T) => [T, any, any] -> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ ->{ dataType: 'a', day: 0 } : { dataType: "a"; day: number; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->dataType : "a" -> : ^^^ ->'a' : "a" -> : ^^^ ->day : number -> : ^^^^^^ ->0 : 0 -> : ^ - - const [x, y, z] = foo({ dataType: 'a', day: 0 }); ->x : { dataType: "a"; day: number; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->y : any -> : ^^^ ->z : any -> : ^^^ ->foo({ dataType: 'a', day: 0 }) : [{ dataType: "a"; day: number; }, any, any] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->foo : (template: T) => [T, any, any] -> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ ->{ dataType: 'a', day: 0 } : { dataType: "a"; day: number; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->dataType : "a" -> : ^^^ ->'a' : "a" -> : ^^^ ->day : number -> : ^^^^^^ ->0 : 0 -> : ^ - - const [,] = bar({ dataType: 'a', day: 0 }); -> : undefined -> : ^^^^^^^^^ ->bar({ dataType: 'a', day: 0 }) : [{ dataType: "a"; day: number; }, any] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->bar : (template: T) => [T, any] -> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ ->{ dataType: 'a', day: 0 } : { dataType: "a"; day: number; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->dataType : "a" -> : ^^^ ->'a' : "a" -> : ^^^ ->day : number -> : ^^^^^^ ->0 : 0 -> : ^ - - const [a, b] = bar({ dataType: 'a', day: 0 }); ->a : { dataType: "a"; day: number; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->b : any -> : ^^^ ->bar({ dataType: 'a', day: 0 }) : [{ dataType: "a"; day: number; }, any] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->bar : (template: T) => [T, any] -> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ ->{ dataType: 'a', day: 0 } : { dataType: "a"; day: number; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->dataType : "a" -> : ^^^ ->'a' : "a" -> : ^^^ ->day : number -> : ^^^^^^ ->0 : 0 -> : ^ - - // These should work but currently don't (this is the bug) - const [, , t] = foo({ dataType: 'a', day: 0 }); // Should not error -> : undefined -> : ^^^^^^^^^ -> : undefined -> : ^^^^^^^^^ ->t : any -> : ^^^ ->foo({ dataType: 'a', day: 0 }) : [{ dataType: DataType; }, any, any] -> : ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ->foo : (template: T) => [T, any, any] -> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ ->{ dataType: 'a', day: 0 } : { dataType: "a"; day: number; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->dataType : "a" -> : ^^^ ->'a' : "a" -> : ^^^ ->day : number -> : ^^^^^^ ->0 : 0 -> : ^ - - const [, u] = bar({ dataType: 'a', day: 0 }); // Should not error -> : undefined -> : ^^^^^^^^^ ->u : any -> : ^^^ ->bar({ dataType: 'a', day: 0 }) : [{ dataType: DataType; }, any] -> : ^^^^^^^^^^^^^ ^^^^^^^^^ ->bar : (template: T) => [T, any] -> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ ->{ dataType: 'a', day: 0 } : { dataType: "a"; day: number; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->dataType : "a" -> : ^^^ ->'a' : "a" -> : ^^^ ->day : number -> : ^^^^^^ ->0 : 0 -> : ^ - - console.log(x, y, z, t, a, b, u); ->console.log(x, y, z, t, a, b, u) : void -> : ^^^^ ->console.log : (...data: any[]) => void -> : ^^^^ ^^ ^^^^^ ->console : Console -> : ^^^^^^^ ->log : (...data: any[]) => void -> : ^^^^ ^^ ^^^^^ ->x : { dataType: "a"; day: number; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->y : any ->z : any ->t : any ->a : { dataType: "a"; day: number; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->b : any ->u : any -} - -// Test that direct calls work fine (they do) -function testDirectCalls() { ->testDirectCalls : () => void -> : ^^^^^^^^^^ - - const result1 = foo({ dataType: 'a', day: 0 }); ->result1 : [{ dataType: "a"; day: number; }, any, any] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->foo({ dataType: 'a', day: 0 }) : [{ dataType: "a"; day: number; }, any, any] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->foo : (template: T) => [T, any, any] -> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ ->{ dataType: 'a', day: 0 } : { dataType: "a"; day: number; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->dataType : "a" -> : ^^^ ->'a' : "a" -> : ^^^ ->day : number -> : ^^^^^^ ->0 : 0 -> : ^ - - const result2 = bar({ dataType: 'a', day: 0 }); ->result2 : [{ dataType: "a"; day: number; }, any] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->bar({ dataType: 'a', day: 0 }) : [{ dataType: "a"; day: number; }, any] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->bar : (template: T) => [T, any] -> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ ->{ dataType: 'a', day: 0 } : { dataType: "a"; day: number; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->dataType : "a" -> : ^^^ ->'a' : "a" -> : ^^^ ->day : number -> : ^^^^^^ ->0 : 0 -> : ^ - - console.log(result1, result2); ->console.log(result1, result2) : void -> : ^^^^ ->console.log : (...data: any[]) => void -> : ^^^^ ^^ ^^^^^ ->console : Console -> : ^^^^^^^ ->log : (...data: any[]) => void -> : ^^^^ ^^ ^^^^^ ->result1 : [{ dataType: "a"; day: number; }, any, any] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->result2 : [{ dataType: "a"; day: number; }, any] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -} diff --git a/tests/cases/compiler/destructuringAssignmentWithConstraints.ts b/tests/cases/compiler/destructuringAssignmentWithConstraints.ts deleted file mode 100644 index 45af10ea695..00000000000 --- a/tests/cases/compiler/destructuringAssignmentWithConstraints.ts +++ /dev/null @@ -1,27 +0,0 @@ -// Test case for destructuring assignment with generic constraints issue - -type DataType = 'a' | 'b'; - -declare function foo(template: T): [T, any, any]; -declare function bar(template: T): [T, any]; - -function testDestructuringBug() { - // These work fine (and should continue to work) - const [, ,] = foo({ dataType: 'a', day: 0 }); - const [x, y, z] = foo({ dataType: 'a', day: 0 }); - const [,] = bar({ dataType: 'a', day: 0 }); - const [a, b] = bar({ dataType: 'a', day: 0 }); - - // These should work but currently don't (this is the bug) - const [, , t] = foo({ dataType: 'a', day: 0 }); // Should not error - const [, u] = bar({ dataType: 'a', day: 0 }); // Should not error - - console.log(x, y, z, t, a, b, u); -} - -// Test that direct calls work fine (they do) -function testDirectCalls() { - const result1 = foo({ dataType: 'a', day: 0 }); - const result2 = bar({ dataType: 'a', day: 0 }); - console.log(result1, result2); -} \ No newline at end of file