diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts
index a40d66280ea9e..6188cc1ace6f3 100644
--- a/src/compiler/binder.ts
+++ b/src/compiler/binder.ts
@@ -657,11 +657,15 @@ namespace ts {
                 const saveExceptionTarget = currentExceptionTarget;
                 const saveActiveLabelList = activeLabelList;
                 const saveHasExplicitReturn = hasExplicitReturn;
-                const isIIFE = containerFlags & ContainerFlags.IsFunctionExpression && !hasSyntacticModifier(node, ModifierFlags.Async) &&
-                    !(node as FunctionLikeDeclaration).asteriskToken && !!getImmediatelyInvokedFunctionExpression(node);
+                const isImmediatelyInvoked =
+                    (containerFlags & ContainerFlags.IsFunctionExpression &&
+                        !hasSyntacticModifier(node, ModifierFlags.Async) &&
+                        !(node as FunctionLikeDeclaration).asteriskToken &&
+                        !!getImmediatelyInvokedFunctionExpression(node)) ||
+                    node.kind === SyntaxKind.ClassStaticBlockDeclaration;
                 // A non-async, non-generator IIFE is considered part of the containing control flow. Return statements behave
                 // similarly to break statements that exit to a label just past the statement body.
-                if (!isIIFE) {
+                if (!isImmediatelyInvoked) {
                     currentFlow = initFlowNode({ flags: FlowFlags.Start });
                     if (containerFlags & (ContainerFlags.IsFunctionExpression | ContainerFlags.IsObjectLiteralOrClassExpressionMethodOrAccessor)) {
                         currentFlow.node = node as FunctionExpression | ArrowFunction | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration;
@@ -669,7 +673,7 @@ namespace ts {
                 }
                 // We create a return control flow graph for IIFEs and constructors. For constructors
                 // we use the return control flow graph in strict property initialization checks.
-                currentReturnTarget = isIIFE || node.kind === SyntaxKind.Constructor || node.kind === SyntaxKind.ClassStaticBlockDeclaration || (isInJSFile(node) && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression)) ? createBranchLabel() : undefined;
+                currentReturnTarget = isImmediatelyInvoked || node.kind === SyntaxKind.Constructor || (isInJSFile(node) && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression)) ? createBranchLabel() : undefined;
                 currentExceptionTarget = undefined;
                 currentBreakTarget = undefined;
                 currentContinueTarget = undefined;
@@ -695,7 +699,7 @@ namespace ts {
                         (node as FunctionLikeDeclaration | ClassStaticBlockDeclaration).returnFlowNode = currentFlow;
                     }
                 }
-                if (!isIIFE) {
+                if (!isImmediatelyInvoked) {
                     currentFlow = saveCurrentFlow;
                 }
                 currentBreakTarget = saveBreakTarget;
diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index eee32406b7790..ee00a28b5f1fd 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -28852,6 +28852,7 @@ namespace ts {
                 && !isOptionalPropertyDeclaration(valueDeclaration)
                 && !(isAccessExpression(node) && isAccessExpression(node.expression))
                 && !isBlockScopedNameDeclaredBeforeUse(valueDeclaration, right)
+                && !(isMethodDeclaration(valueDeclaration) && getCombinedModifierFlags(valueDeclaration) & ModifierFlags.Static)
                 && (compilerOptions.useDefineForClassFields || !isPropertyDeclaredInAncestorClass(prop))) {
                 diagnosticMessage = error(right, Diagnostics.Property_0_is_used_before_its_initialization, declarationName);
             }
diff --git a/tests/baselines/reference/classStaticBlock28.js b/tests/baselines/reference/classStaticBlock28.js
new file mode 100644
index 0000000000000..955dc88d3cfd7
--- /dev/null
+++ b/tests/baselines/reference/classStaticBlock28.js
@@ -0,0 +1,23 @@
+//// [classStaticBlock28.ts]
+let foo: number;
+
+class C {
+    static {
+        foo = 1
+    }
+}
+
+console.log(foo)
+
+//// [classStaticBlock28.js]
+"use strict";
+var foo;
+var C = /** @class */ (function () {
+    function C() {
+    }
+    return C;
+}());
+(function () {
+    foo = 1;
+})();
+console.log(foo);
diff --git a/tests/baselines/reference/classStaticBlock28.symbols b/tests/baselines/reference/classStaticBlock28.symbols
new file mode 100644
index 0000000000000..3a8dc99b9d194
--- /dev/null
+++ b/tests/baselines/reference/classStaticBlock28.symbols
@@ -0,0 +1,19 @@
+=== tests/cases/conformance/classes/classStaticBlock/classStaticBlock28.ts ===
+let foo: number;
+>foo : Symbol(foo, Decl(classStaticBlock28.ts, 0, 3))
+
+class C {
+>C : Symbol(C, Decl(classStaticBlock28.ts, 0, 16))
+
+    static {
+        foo = 1
+>foo : Symbol(foo, Decl(classStaticBlock28.ts, 0, 3))
+    }
+}
+
+console.log(foo)
+>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, --, --))
+>foo : Symbol(foo, Decl(classStaticBlock28.ts, 0, 3))
+
diff --git a/tests/baselines/reference/classStaticBlock28.types b/tests/baselines/reference/classStaticBlock28.types
new file mode 100644
index 0000000000000..8abbe617d9f5c
--- /dev/null
+++ b/tests/baselines/reference/classStaticBlock28.types
@@ -0,0 +1,22 @@
+=== tests/cases/conformance/classes/classStaticBlock/classStaticBlock28.ts ===
+let foo: number;
+>foo : number
+
+class C {
+>C : C
+
+    static {
+        foo = 1
+>foo = 1 : 1
+>foo : number
+>1 : 1
+    }
+}
+
+console.log(foo)
+>console.log(foo) : void
+>console.log : (...data: any[]) => void
+>console : Console
+>log : (...data: any[]) => void
+>foo : number
+
diff --git a/tests/baselines/reference/classStaticBlockUseBeforeDef3.errors.txt b/tests/baselines/reference/classStaticBlockUseBeforeDef3.errors.txt
new file mode 100644
index 0000000000000..7fed7444b57ef
--- /dev/null
+++ b/tests/baselines/reference/classStaticBlockUseBeforeDef3.errors.txt
@@ -0,0 +1,53 @@
+tests/cases/conformance/classes/classStaticBlock/classStaticBlockUseBeforeDef3.ts(14,21): error TS2448: Block-scoped variable 'FOO' used before its declaration.
+tests/cases/conformance/classes/classStaticBlock/classStaticBlockUseBeforeDef3.ts(14,21): error TS2454: Variable 'FOO' is used before being assigned.
+
+
+==== tests/cases/conformance/classes/classStaticBlock/classStaticBlockUseBeforeDef3.ts (2 errors) ====
+    class A {
+        static {
+            A.doSomething(); // should not error
+        }
+    
+        static doSomething() {
+           console.log("gotcha!");
+        }
+    }
+    
+    
+    class Baz {
+        static {
+            console.log(FOO);   // should error
+                        ~~~
+!!! error TS2448: Block-scoped variable 'FOO' used before its declaration.
+!!! related TS2728 tests/cases/conformance/classes/classStaticBlock/classStaticBlockUseBeforeDef3.ts:18:7: 'FOO' is declared here.
+                        ~~~
+!!! error TS2454: Variable 'FOO' is used before being assigned.
+        }
+    }
+    
+    const FOO = "FOO";
+    class Bar {
+        static {
+            console.log(FOO); // should not error
+        }
+    }
+    
+    let u = "FOO" as "FOO" | "BAR";
+    
+    class CFA {
+        static {
+            u = "BAR";
+            u;  // should be "BAR"
+        }
+    
+        static t = 1;
+    
+        static doSomething() {}
+    
+        static {
+            u;  // should be "BAR"
+        }
+    }
+    
+    u; // should be "BAR"
+    
\ No newline at end of file
diff --git a/tests/baselines/reference/classStaticBlockUseBeforeDef3.symbols b/tests/baselines/reference/classStaticBlockUseBeforeDef3.symbols
new file mode 100644
index 0000000000000..beb214dab0860
--- /dev/null
+++ b/tests/baselines/reference/classStaticBlockUseBeforeDef3.symbols
@@ -0,0 +1,78 @@
+=== tests/cases/conformance/classes/classStaticBlock/classStaticBlockUseBeforeDef3.ts ===
+class A {
+>A : Symbol(A, Decl(classStaticBlockUseBeforeDef3.ts, 0, 0))
+
+    static {
+        A.doSomething(); // should not error
+>A.doSomething : Symbol(A.doSomething, Decl(classStaticBlockUseBeforeDef3.ts, 3, 5))
+>A : Symbol(A, Decl(classStaticBlockUseBeforeDef3.ts, 0, 0))
+>doSomething : Symbol(A.doSomething, Decl(classStaticBlockUseBeforeDef3.ts, 3, 5))
+    }
+
+    static doSomething() {
+>doSomething : Symbol(A.doSomething, Decl(classStaticBlockUseBeforeDef3.ts, 3, 5))
+
+       console.log("gotcha!");
+>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, --, --))
+    }
+}
+
+
+class Baz {
+>Baz : Symbol(Baz, Decl(classStaticBlockUseBeforeDef3.ts, 8, 1))
+
+    static {
+        console.log(FOO);   // should error
+>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, --, --))
+>FOO : Symbol(FOO, Decl(classStaticBlockUseBeforeDef3.ts, 17, 5))
+    }
+}
+
+const FOO = "FOO";
+>FOO : Symbol(FOO, Decl(classStaticBlockUseBeforeDef3.ts, 17, 5))
+
+class Bar {
+>Bar : Symbol(Bar, Decl(classStaticBlockUseBeforeDef3.ts, 17, 18))
+
+    static {
+        console.log(FOO); // should not error
+>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, --, --))
+>FOO : Symbol(FOO, Decl(classStaticBlockUseBeforeDef3.ts, 17, 5))
+    }
+}
+
+let u = "FOO" as "FOO" | "BAR";
+>u : Symbol(u, Decl(classStaticBlockUseBeforeDef3.ts, 24, 3))
+
+class CFA {
+>CFA : Symbol(CFA, Decl(classStaticBlockUseBeforeDef3.ts, 24, 31))
+
+    static {
+        u = "BAR";
+>u : Symbol(u, Decl(classStaticBlockUseBeforeDef3.ts, 24, 3))
+
+        u;  // should be "BAR"
+>u : Symbol(u, Decl(classStaticBlockUseBeforeDef3.ts, 24, 3))
+    }
+
+    static t = 1;
+>t : Symbol(CFA.t, Decl(classStaticBlockUseBeforeDef3.ts, 30, 5))
+
+    static doSomething() {}
+>doSomething : Symbol(CFA.doSomething, Decl(classStaticBlockUseBeforeDef3.ts, 32, 17))
+
+    static {
+        u;  // should be "BAR"
+>u : Symbol(u, Decl(classStaticBlockUseBeforeDef3.ts, 24, 3))
+    }
+}
+
+u; // should be "BAR"
+>u : Symbol(u, Decl(classStaticBlockUseBeforeDef3.ts, 24, 3))
+
diff --git a/tests/baselines/reference/classStaticBlockUseBeforeDef3.types b/tests/baselines/reference/classStaticBlockUseBeforeDef3.types
new file mode 100644
index 0000000000000..f10c2ee0f67a1
--- /dev/null
+++ b/tests/baselines/reference/classStaticBlockUseBeforeDef3.types
@@ -0,0 +1,89 @@
+=== tests/cases/conformance/classes/classStaticBlock/classStaticBlockUseBeforeDef3.ts ===
+class A {
+>A : A
+
+    static {
+        A.doSomething(); // should not error
+>A.doSomething() : void
+>A.doSomething : () => void
+>A : typeof A
+>doSomething : () => void
+    }
+
+    static doSomething() {
+>doSomething : () => void
+
+       console.log("gotcha!");
+>console.log("gotcha!") : void
+>console.log : (...data: any[]) => void
+>console : Console
+>log : (...data: any[]) => void
+>"gotcha!" : "gotcha!"
+    }
+}
+
+
+class Baz {
+>Baz : Baz
+
+    static {
+        console.log(FOO);   // should error
+>console.log(FOO) : void
+>console.log : (...data: any[]) => void
+>console : Console
+>log : (...data: any[]) => void
+>FOO : "FOO"
+    }
+}
+
+const FOO = "FOO";
+>FOO : "FOO"
+>"FOO" : "FOO"
+
+class Bar {
+>Bar : Bar
+
+    static {
+        console.log(FOO); // should not error
+>console.log(FOO) : void
+>console.log : (...data: any[]) => void
+>console : Console
+>log : (...data: any[]) => void
+>FOO : "FOO"
+    }
+}
+
+let u = "FOO" as "FOO" | "BAR";
+>u : "FOO" | "BAR"
+>"FOO" as "FOO" | "BAR" : "FOO" | "BAR"
+>"FOO" : "FOO"
+
+class CFA {
+>CFA : CFA
+
+    static {
+        u = "BAR";
+>u = "BAR" : "BAR"
+>u : "FOO" | "BAR"
+>"BAR" : "BAR"
+
+        u;  // should be "BAR"
+>u : "BAR"
+    }
+
+    static t = 1;
+>t : number
+>1 : 1
+
+    static doSomething() {}
+>doSomething : () => void
+
+    static {
+        u;  // should be "BAR"
+>u : "BAR"
+    }
+}
+
+u; // should be "BAR"
+>u : "BAR"
+
diff --git a/tests/cases/conformance/classes/classStaticBlock/classStaticBlock28.ts b/tests/cases/conformance/classes/classStaticBlock/classStaticBlock28.ts
new file mode 100644
index 0000000000000..90cbf78bfdd59
--- /dev/null
+++ b/tests/cases/conformance/classes/classStaticBlock/classStaticBlock28.ts
@@ -0,0 +1,11 @@
+// @strict: true
+
+let foo: number;
+
+class C {
+    static {
+        foo = 1
+    }
+}
+
+console.log(foo)
\ No newline at end of file
diff --git a/tests/cases/conformance/classes/classStaticBlock/classStaticBlockUseBeforeDef3.ts b/tests/cases/conformance/classes/classStaticBlock/classStaticBlockUseBeforeDef3.ts
new file mode 100644
index 0000000000000..bf59cb8a8c485
--- /dev/null
+++ b/tests/cases/conformance/classes/classStaticBlock/classStaticBlockUseBeforeDef3.ts
@@ -0,0 +1,45 @@
+// @noEmit: true
+// @strict: true
+
+class A {
+    static {
+        A.doSomething(); // should not error
+    }
+
+    static doSomething() {
+       console.log("gotcha!");
+    }
+}
+
+
+class Baz {
+    static {
+        console.log(FOO);   // should error
+    }
+}
+
+const FOO = "FOO";
+class Bar {
+    static {
+        console.log(FOO); // should not error
+    }
+}
+
+let u = "FOO" as "FOO" | "BAR";
+
+class CFA {
+    static {
+        u = "BAR";
+        u;  // should be "BAR"
+    }
+
+    static t = 1;
+
+    static doSomething() {}
+
+    static {
+        u;  // should be "BAR"
+    }
+}
+
+u; // should be "BAR"