Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/compiler/resolutionCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import {
ModeAwareCache,
ModuleResolutionCache,
moduleResolutionNameAndModeGetter,
Mutable,
mutateMap,
noopFileWatcher,
normalizePath,
Expand Down Expand Up @@ -556,7 +557,7 @@ function resolveModuleNameUsingGlobalCache(
);
if (resolvedModule) {
// Modify existing resolution so its saved in the directory cache as well
(primaryResult.resolvedModule as any) = resolvedModule;
(primaryResult as Mutable<typeof primaryResult>).resolvedModule = resolvedModule;
primaryResult.failedLookupLocations = updateResolutionField(primaryResult.failedLookupLocations, failedLookupLocations);
primaryResult.affectingLocations = updateResolutionField(primaryResult.affectingLocations, affectingLocations);
primaryResult.resolutionDiagnostics = updateResolutionField(primaryResult.resolutionDiagnostics, resolutionDiagnostics);
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4815,6 +4815,8 @@ function getAssignmentTarget(node: Node): AssignmentTarget | undefined {
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.SpreadElement:
case SyntaxKind.NonNullExpression:
case SyntaxKind.TypeAssertionExpression:
case SyntaxKind.AsExpression:
node = parent;
break;
case SyntaxKind.SpreadAssignment:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
classNameReferencesInStaticElements.ts(12,2): error TS2629: Cannot assign to 'Foo' because it is a class.


==== classNameReferencesInStaticElements.ts (1 errors) ====
// https://github.com/microsoft/TypeScript/issues/54607
class Foo {
static { console.log(this, Foo) }
static x = () => { console.log(this, Foo) }
static y = function(this: unknown) { console.log(this, Foo) }

#x() { console.log(Foo); }
x() { this.#x(); }
}

const oldFoo = Foo;
(Foo as any) = null;
~~~
!!! error TS2629: Cannot assign to 'Foo' because it is a class.
oldFoo.x();
oldFoo.y();
new oldFoo().x();
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
usedBeforeAssignedTypeAssertion.ts(28,6): error TS2588: Cannot assign to 'm' because it is a constant.
usedBeforeAssignedTypeAssertion.ts(41,10): error TS2540: Cannot assign to 'prop' because it is a read-only property.
usedBeforeAssignedTypeAssertion.ts(47,12): error TS2454: Variable 'uninitialized' is used before being assigned.


==== usedBeforeAssignedTypeAssertion.ts (3 errors) ====
// Test case for type assertion (angle bracket syntax) - assignment should not error
function testTypeAssertion() {
let x: number;
(<any>x) = 42; // Should not error - this is an assignment
}

// Test case for 'as' expression - assignment should not error
function testAsExpression() {
let y: number;
(y as any) = 42; // Should not error - this is an assignment
}

// Test case for parenthesized expression (should already work)
function testParentheses() {
let z: number;
(z) = 42; // Should not error - this is an assignment
}

// Test case with nested type assertions
function testNested() {
let nested: any;
((nested as any) as unknown) = "test"; // Should not error
}

// Test case for const assignment via type assertion - should error
function testConstAssignment() {
const m = 32;
(m as any) = 16; // Should error - cannot assign to const
~
!!! error TS2588: Cannot assign to 'm' because it is a constant.
}

// Test case for readonly property assignment via type assertion - should error
function testReadonlyPropertyAssignment() {
interface ReadonlyInterface {
readonly prop: number;
}

let obj: ReadonlyInterface;
obj = { prop: 42 };

// Should error - cannot assign to readonly property, even through type assertion
(obj.prop as any) = 100;
~~~~
!!! error TS2540: Cannot assign to 'prop' because it is a read-only property.
}

// Test cases that should still produce errors for proper context
function shouldStillError() {
let uninitialized: number;
return uninitialized; // Should error - never assigned
~~~~~~~~~~~~~
!!! error TS2454: Variable 'uninitialized' is used before being assigned.
}
91 changes: 91 additions & 0 deletions tests/baselines/reference/usedBeforeAssignedTypeAssertion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//// [tests/cases/compiler/usedBeforeAssignedTypeAssertion.ts] ////

//// [usedBeforeAssignedTypeAssertion.ts]
// Test case for type assertion (angle bracket syntax) - assignment should not error
function testTypeAssertion() {
let x: number;
(<any>x) = 42; // Should not error - this is an assignment
}

// Test case for 'as' expression - assignment should not error
function testAsExpression() {
let y: number;
(y as any) = 42; // Should not error - this is an assignment
}

// Test case for parenthesized expression (should already work)
function testParentheses() {
let z: number;
(z) = 42; // Should not error - this is an assignment
}

// Test case with nested type assertions
function testNested() {
let nested: any;
((nested as any) as unknown) = "test"; // Should not error
}

// Test case for const assignment via type assertion - should error
function testConstAssignment() {
const m = 32;
(m as any) = 16; // Should error - cannot assign to const
}

// Test case for readonly property assignment via type assertion - should error
function testReadonlyPropertyAssignment() {
interface ReadonlyInterface {
readonly prop: number;
}

let obj: ReadonlyInterface;
obj = { prop: 42 };

// Should error - cannot assign to readonly property, even through type assertion
(obj.prop as any) = 100;
}

// Test cases that should still produce errors for proper context
function shouldStillError() {
let uninitialized: number;
return uninitialized; // Should error - never assigned
}

//// [usedBeforeAssignedTypeAssertion.js]
"use strict";
// Test case for type assertion (angle bracket syntax) - assignment should not error
function testTypeAssertion() {
var x;
x = 42; // Should not error - this is an assignment
}
// Test case for 'as' expression - assignment should not error
function testAsExpression() {
var y;
y = 42; // Should not error - this is an assignment
}
// Test case for parenthesized expression (should already work)
function testParentheses() {
var z;
(z) = 42; // Should not error - this is an assignment
}
// Test case with nested type assertions
function testNested() {
var nested;
nested = "test"; // Should not error
}
// Test case for const assignment via type assertion - should error
function testConstAssignment() {
var m = 32;
m = 16; // Should error - cannot assign to const
}
// Test case for readonly property assignment via type assertion - should error
function testReadonlyPropertyAssignment() {
var obj;
obj = { prop: 42 };
// Should error - cannot assign to readonly property, even through type assertion
obj.prop = 100;
}
// Test cases that should still produce errors for proper context
function shouldStillError() {
var uninitialized;
return uninitialized; // Should error - never assigned
}
94 changes: 94 additions & 0 deletions tests/baselines/reference/usedBeforeAssignedTypeAssertion.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
//// [tests/cases/compiler/usedBeforeAssignedTypeAssertion.ts] ////

=== usedBeforeAssignedTypeAssertion.ts ===
// Test case for type assertion (angle bracket syntax) - assignment should not error
function testTypeAssertion() {
>testTypeAssertion : Symbol(testTypeAssertion, Decl(usedBeforeAssignedTypeAssertion.ts, 0, 0))

let x: number;
>x : Symbol(x, Decl(usedBeforeAssignedTypeAssertion.ts, 2, 7))

(<any>x) = 42; // Should not error - this is an assignment
>x : Symbol(x, Decl(usedBeforeAssignedTypeAssertion.ts, 2, 7))
}

// Test case for 'as' expression - assignment should not error
function testAsExpression() {
>testAsExpression : Symbol(testAsExpression, Decl(usedBeforeAssignedTypeAssertion.ts, 4, 1))

let y: number;
>y : Symbol(y, Decl(usedBeforeAssignedTypeAssertion.ts, 8, 7))

(y as any) = 42; // Should not error - this is an assignment
>y : Symbol(y, Decl(usedBeforeAssignedTypeAssertion.ts, 8, 7))
}

// Test case for parenthesized expression (should already work)
function testParentheses() {
>testParentheses : Symbol(testParentheses, Decl(usedBeforeAssignedTypeAssertion.ts, 10, 1))

let z: number;
>z : Symbol(z, Decl(usedBeforeAssignedTypeAssertion.ts, 14, 7))

(z) = 42; // Should not error - this is an assignment
>z : Symbol(z, Decl(usedBeforeAssignedTypeAssertion.ts, 14, 7))
}

// Test case with nested type assertions
function testNested() {
>testNested : Symbol(testNested, Decl(usedBeforeAssignedTypeAssertion.ts, 16, 1))

let nested: any;
>nested : Symbol(nested, Decl(usedBeforeAssignedTypeAssertion.ts, 20, 7))

((nested as any) as unknown) = "test"; // Should not error
>nested : Symbol(nested, Decl(usedBeforeAssignedTypeAssertion.ts, 20, 7))
}

// Test case for const assignment via type assertion - should error
function testConstAssignment() {
>testConstAssignment : Symbol(testConstAssignment, Decl(usedBeforeAssignedTypeAssertion.ts, 22, 1))

const m = 32;
>m : Symbol(m, Decl(usedBeforeAssignedTypeAssertion.ts, 26, 9))

(m as any) = 16; // Should error - cannot assign to const
>m : Symbol(m, Decl(usedBeforeAssignedTypeAssertion.ts, 26, 9))
}

// Test case for readonly property assignment via type assertion - should error
function testReadonlyPropertyAssignment() {
>testReadonlyPropertyAssignment : Symbol(testReadonlyPropertyAssignment, Decl(usedBeforeAssignedTypeAssertion.ts, 28, 1))

interface ReadonlyInterface {
>ReadonlyInterface : Symbol(ReadonlyInterface, Decl(usedBeforeAssignedTypeAssertion.ts, 31, 43))

readonly prop: number;
>prop : Symbol(ReadonlyInterface.prop, Decl(usedBeforeAssignedTypeAssertion.ts, 32, 33))
}

let obj: ReadonlyInterface;
>obj : Symbol(obj, Decl(usedBeforeAssignedTypeAssertion.ts, 36, 7))
>ReadonlyInterface : Symbol(ReadonlyInterface, Decl(usedBeforeAssignedTypeAssertion.ts, 31, 43))

obj = { prop: 42 };
>obj : Symbol(obj, Decl(usedBeforeAssignedTypeAssertion.ts, 36, 7))
>prop : Symbol(prop, Decl(usedBeforeAssignedTypeAssertion.ts, 37, 11))

// Should error - cannot assign to readonly property, even through type assertion
(obj.prop as any) = 100;
>obj.prop : Symbol(ReadonlyInterface.prop, Decl(usedBeforeAssignedTypeAssertion.ts, 32, 33))
>obj : Symbol(obj, Decl(usedBeforeAssignedTypeAssertion.ts, 36, 7))
>prop : Symbol(ReadonlyInterface.prop, Decl(usedBeforeAssignedTypeAssertion.ts, 32, 33))
}

// Test cases that should still produce errors for proper context
function shouldStillError() {
>shouldStillError : Symbol(shouldStillError, Decl(usedBeforeAssignedTypeAssertion.ts, 41, 1))

let uninitialized: number;
>uninitialized : Symbol(uninitialized, Decl(usedBeforeAssignedTypeAssertion.ts, 45, 7))

return uninitialized; // Should error - never assigned
>uninitialized : Symbol(uninitialized, Decl(usedBeforeAssignedTypeAssertion.ts, 45, 7))
}
Loading
Loading