diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8b53ecbf19..cf374acd97 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -574,18 +574,28 @@ namespace ts { function isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration: VariableDeclaration, usage: Node): boolean { const container = getEnclosingBlockScopeContainer(declaration); - if (declaration.parent.parent.kind === SyntaxKind.VariableStatement || - declaration.parent.parent.kind === SyntaxKind.ForStatement) { - // variable statement/for statement case, - // use site should not be inside variable declaration (initializer of declaration or binding element) - return isSameScopeDescendentOf(usage, declaration, container); + switch (declaration.parent.parent.kind) { + case SyntaxKind.VariableStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForOfStatement: + // variable statement/for/for-of statement case, + // use site should not be inside variable declaration (initializer of declaration or binding element) + if (isSameScopeDescendentOf(usage, declaration, container)) { + return true; + } + break; } - else if (declaration.parent.parent.kind === SyntaxKind.ForOfStatement || - declaration.parent.parent.kind === SyntaxKind.ForInStatement) { - // ForIn/ForOf case - use site should not be used in expression part - const expression = (declaration.parent.parent).expression; - return isSameScopeDescendentOf(usage, expression, container); + + switch (declaration.parent.parent.kind) { + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + // ForIn/ForOf case - use site should not be used in expression part + if (isSameScopeDescendentOf(usage, (declaration.parent.parent).expression, container)) { + return true; + } } + + return false; } function isUsedInFunctionOrNonStaticProperty(declaration: Declaration, usage: Node): boolean { diff --git a/tests/baselines/reference/blockScopedBindingUsedBeforeDef.errors.txt b/tests/baselines/reference/blockScopedBindingUsedBeforeDef.errors.txt new file mode 100644 index 0000000000..55b5c9dab2 --- /dev/null +++ b/tests/baselines/reference/blockScopedBindingUsedBeforeDef.errors.txt @@ -0,0 +1,23 @@ +tests/cases/compiler/blockScopedBindingUsedBeforeDef.ts(2,12): error TS2448: Block-scoped variable 'a' used before its declaration. +tests/cases/compiler/blockScopedBindingUsedBeforeDef.ts(5,12): error TS2448: Block-scoped variable 'a' used before its declaration. +tests/cases/compiler/blockScopedBindingUsedBeforeDef.ts(5,35): error TS7027: Unreachable code detected. +tests/cases/compiler/blockScopedBindingUsedBeforeDef.ts(8,7): error TS2448: Block-scoped variable 'b' used before its declaration. + + +==== tests/cases/compiler/blockScopedBindingUsedBeforeDef.ts (4 errors) ==== + // 1: + for (let {[a]: a} of [{ }]) continue; + ~ +!!! error TS2448: Block-scoped variable 'a' used before its declaration. + + // 2: + for (let {[a]: a} = { }; false; ) continue; + ~ +!!! error TS2448: Block-scoped variable 'a' used before its declaration. + ~~~~~~~~ +!!! error TS7027: Unreachable code detected. + + // 3: + let {[b]: b} = { }; + ~ +!!! error TS2448: Block-scoped variable 'b' used before its declaration. \ No newline at end of file diff --git a/tests/baselines/reference/blockScopedBindingUsedBeforeDef.js b/tests/baselines/reference/blockScopedBindingUsedBeforeDef.js new file mode 100644 index 0000000000..cc9ad56be8 --- /dev/null +++ b/tests/baselines/reference/blockScopedBindingUsedBeforeDef.js @@ -0,0 +1,21 @@ +//// [blockScopedBindingUsedBeforeDef.ts] +// 1: +for (let {[a]: a} of [{ }]) continue; + +// 2: +for (let {[a]: a} = { }; false; ) continue; + +// 3: +let {[b]: b} = { }; + +//// [blockScopedBindingUsedBeforeDef.js] +// 1: +for (var _i = 0, _a = [{}]; _i < _a.length; _i++) { + var _b = a, a = _a[_i][_b]; + continue; +} +// 2: +for (var _c = a, a = {}[_c]; false;) + continue; +// 3: +var _d = b, b = {}[_d]; diff --git a/tests/cases/compiler/blockScopedBindingUsedBeforeDef.ts b/tests/cases/compiler/blockScopedBindingUsedBeforeDef.ts new file mode 100644 index 0000000000..c0b803df6e --- /dev/null +++ b/tests/cases/compiler/blockScopedBindingUsedBeforeDef.ts @@ -0,0 +1,8 @@ +// 1: +for (let {[a]: a} of [{ }]) continue; + +// 2: +for (let {[a]: a} = { }; false; ) continue; + +// 3: +let {[b]: b} = { }; \ No newline at end of file