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
19 changes: 9 additions & 10 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29247,26 +29247,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const symbol = getResolvedSymbol(expr);
if (isConstantVariable(symbol)) {
const declaration = symbol.valueDeclaration!;
let initializer = getCandidateVariableDeclarationInitializer(declaration);
// Given 'const x = obj.kind', allow 'x' as an alias for 'obj.kind'
if (
isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer) &&
isMatchingReference(reference, declaration.initializer.expression)
) {
return declaration.initializer;
if (initializer && isAccessExpression(initializer) && isMatchingReference(reference, initializer.expression)) {
return initializer;
}
// Given 'const { kind: x } = obj', allow 'x' as an alias for 'obj.kind'
if (isBindingElement(declaration) && !declaration.initializer) {
const parent = declaration.parent.parent;
if (
isVariableDeclaration(parent) && !parent.type && parent.initializer && (isIdentifier(parent.initializer) || isAccessExpression(parent.initializer)) &&
isMatchingReference(reference, parent.initializer)
) {
initializer = getCandidateVariableDeclarationInitializer(declaration.parent.parent);
if (initializer && (isIdentifier(initializer) || isAccessExpression(initializer)) && isMatchingReference(reference, initializer)) {
return declaration;
}
}
}
}
return undefined;

function getCandidateVariableDeclarationInitializer(node: Node) {
return isVariableDeclaration(node) && !node.type && node.initializer ? skipParentheses(node.initializer) : undefined;
}
}

function getDiscriminantPropertyAccess(expr: Expression, computedType: Type) {
Expand Down
292 changes: 292 additions & 0 deletions tests/baselines/reference/controlFlowAliasing2.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
//// [tests/cases/conformance/controlFlow/controlFlowAliasing2.ts] ////

=== controlFlowAliasing2.ts ===
// https://github.com/microsoft/TypeScript/issues/61784

type Test = TestA | TestB;
>Test : Symbol(Test, Decl(controlFlowAliasing2.ts, 0, 0))
>TestA : Symbol(TestA, Decl(controlFlowAliasing2.ts, 2, 26))
>TestB : Symbol(TestB, Decl(controlFlowAliasing2.ts, 7, 1))

interface TestA {
>TestA : Symbol(TestA, Decl(controlFlowAliasing2.ts, 2, 26))

type: 'a';
>type : Symbol(TestA.type, Decl(controlFlowAliasing2.ts, 4, 17))

name: string;
>name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
}

interface TestB {
>TestB : Symbol(TestB, Decl(controlFlowAliasing2.ts, 7, 1))

type: 'b';
>type : Symbol(TestB.type, Decl(controlFlowAliasing2.ts, 9, 17))

value: number;
>value : Symbol(TestB.value, Decl(controlFlowAliasing2.ts, 10, 12))
}

function _tcb1(this: { test: Test }) {
>_tcb1 : Symbol(_tcb1, Decl(controlFlowAliasing2.ts, 12, 1))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 14, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 14, 22))
>Test : Symbol(Test, Decl(controlFlowAliasing2.ts, 0, 0))

// TS generated by Angular's Type Check block
const _t1 = (((((this).test)).type));
>_t1 : Symbol(_t1, Decl(controlFlowAliasing2.ts, 16, 7))
>(((this).test)).type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))
>(this).test : Symbol(test, Decl(controlFlowAliasing2.ts, 14, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 14, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 14, 22))
>type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))

if (_t1 === "a") {
>_t1 : Symbol(_t1, Decl(controlFlowAliasing2.ts, 16, 7))

(((((this).test)).name));
>(((this).test)).name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
>(this).test : Symbol(test, Decl(controlFlowAliasing2.ts, 14, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 14, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 14, 22))
>name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
}

// Same as above, without the parenthesis
const _t2 = this.test.type;
>_t2 : Symbol(_t2, Decl(controlFlowAliasing2.ts, 22, 7))
>this.test.type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))
>this.test : Symbol(test, Decl(controlFlowAliasing2.ts, 14, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 14, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 14, 22))
>type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))

if (_t2 === "a") {
>_t2 : Symbol(_t2, Decl(controlFlowAliasing2.ts, 22, 7))

(((((this).test)).name));
>(((this).test)).name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
>(this).test : Symbol(test, Decl(controlFlowAliasing2.ts, 14, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 14, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 14, 22))
>name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
}

// Same as above without parenthesis at both places
const testType = this.test.type;
>testType : Symbol(testType, Decl(controlFlowAliasing2.ts, 28, 7))
>this.test.type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))
>this.test : Symbol(test, Decl(controlFlowAliasing2.ts, 14, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 14, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 14, 22))
>type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))

if (testType === "a") {
>testType : Symbol(testType, Decl(controlFlowAliasing2.ts, 28, 7))

this.test.name;
>this.test.name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
>this.test : Symbol(test, Decl(controlFlowAliasing2.ts, 14, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 14, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 14, 22))
>name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
}
}

function _tcb2(this: { test: Test }) {
>_tcb2 : Symbol(_tcb2, Decl(controlFlowAliasing2.ts, 32, 1))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 34, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 34, 22))
>Test : Symbol(Test, Decl(controlFlowAliasing2.ts, 0, 0))

// TS generated by Angular's Type Check block
const _t1 = (((((this).test)).type));
>_t1 : Symbol(_t1, Decl(controlFlowAliasing2.ts, 36, 7))
>(((this).test)).type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))
>(this).test : Symbol(test, Decl(controlFlowAliasing2.ts, 34, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 34, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 34, 22))
>type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))

if ("a" === _t1) {
>_t1 : Symbol(_t1, Decl(controlFlowAliasing2.ts, 36, 7))

(((((this).test)).name));
>(((this).test)).name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
>(this).test : Symbol(test, Decl(controlFlowAliasing2.ts, 34, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 34, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 34, 22))
>name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
}

// Same as above, without the parenthesis
const _t2 = this.test.type;
>_t2 : Symbol(_t2, Decl(controlFlowAliasing2.ts, 42, 7))
>this.test.type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))
>this.test : Symbol(test, Decl(controlFlowAliasing2.ts, 34, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 34, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 34, 22))
>type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))

if ("a" === _t2) {
>_t2 : Symbol(_t2, Decl(controlFlowAliasing2.ts, 42, 7))

(((((this).test)).name));
>(((this).test)).name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
>(this).test : Symbol(test, Decl(controlFlowAliasing2.ts, 34, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 34, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 34, 22))
>name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
}

// Same as above without parenthesis at both places
const testType = this.test.type;
>testType : Symbol(testType, Decl(controlFlowAliasing2.ts, 48, 7))
>this.test.type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))
>this.test : Symbol(test, Decl(controlFlowAliasing2.ts, 34, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 34, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 34, 22))
>type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))

if ("a" === testType) {
>testType : Symbol(testType, Decl(controlFlowAliasing2.ts, 48, 7))

this.test.name;
>this.test.name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
>this.test : Symbol(test, Decl(controlFlowAliasing2.ts, 34, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 34, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 34, 22))
>name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
}
}

function _tcb3(this: { test: Test }) {
>_tcb3 : Symbol(_tcb3, Decl(controlFlowAliasing2.ts, 52, 1))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 54, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 54, 22))
>Test : Symbol(Test, Decl(controlFlowAliasing2.ts, 0, 0))

const { type: _t1 } = (((((this).test))));
>type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))
>_t1 : Symbol(_t1, Decl(controlFlowAliasing2.ts, 55, 9))
>(this).test : Symbol(test, Decl(controlFlowAliasing2.ts, 54, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 54, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 54, 22))

if (_t1 === "a") {
>_t1 : Symbol(_t1, Decl(controlFlowAliasing2.ts, 55, 9))

(((((this).test)).name));
>(((this).test)).name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
>(this).test : Symbol(test, Decl(controlFlowAliasing2.ts, 54, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 54, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 54, 22))
>name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
}

// Same as above, without the parenthesis
const { type: _t2 } = this.test;
>type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))
>_t2 : Symbol(_t2, Decl(controlFlowAliasing2.ts, 61, 9))
>this.test : Symbol(test, Decl(controlFlowAliasing2.ts, 54, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 54, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 54, 22))

if (_t2 === "a") {
>_t2 : Symbol(_t2, Decl(controlFlowAliasing2.ts, 61, 9))

(((((this).test)).name));
>(((this).test)).name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
>(this).test : Symbol(test, Decl(controlFlowAliasing2.ts, 54, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 54, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 54, 22))
>name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
}

// Same as above without parenthesis at both places
const { type: testType } = this.test;
>type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))
>testType : Symbol(testType, Decl(controlFlowAliasing2.ts, 67, 9))
>this.test : Symbol(test, Decl(controlFlowAliasing2.ts, 54, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 54, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 54, 22))

if (testType === "a") {
>testType : Symbol(testType, Decl(controlFlowAliasing2.ts, 67, 9))

this.test.name;
>this.test.name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
>this.test : Symbol(test, Decl(controlFlowAliasing2.ts, 54, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 54, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 54, 22))
>name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
}
}

function _tcb4(this: { test: Test }) {
>_tcb4 : Symbol(_tcb4, Decl(controlFlowAliasing2.ts, 71, 1))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 73, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 73, 22))
>Test : Symbol(Test, Decl(controlFlowAliasing2.ts, 0, 0))

const { type: _t1 } = (((((this).test))));
>type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))
>_t1 : Symbol(_t1, Decl(controlFlowAliasing2.ts, 74, 9))
>(this).test : Symbol(test, Decl(controlFlowAliasing2.ts, 73, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 73, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 73, 22))

if ("a" === _t1) {
>_t1 : Symbol(_t1, Decl(controlFlowAliasing2.ts, 74, 9))

(((((this).test)).name));
>(((this).test)).name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
>(this).test : Symbol(test, Decl(controlFlowAliasing2.ts, 73, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 73, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 73, 22))
>name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
}

// Same as above, without the parenthesis
const { type: _t2 } = this.test;
>type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))
>_t2 : Symbol(_t2, Decl(controlFlowAliasing2.ts, 80, 9))
>this.test : Symbol(test, Decl(controlFlowAliasing2.ts, 73, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 73, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 73, 22))

if ("a" === _t2) {
>_t2 : Symbol(_t2, Decl(controlFlowAliasing2.ts, 80, 9))

(((((this).test)).name));
>(((this).test)).name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
>(this).test : Symbol(test, Decl(controlFlowAliasing2.ts, 73, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 73, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 73, 22))
>name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
}

// Same as above without parenthesis at both places
const { type: testType } = this.test;
>type : Symbol(type, Decl(controlFlowAliasing2.ts, 4, 17), Decl(controlFlowAliasing2.ts, 9, 17))
>testType : Symbol(testType, Decl(controlFlowAliasing2.ts, 86, 9))
>this.test : Symbol(test, Decl(controlFlowAliasing2.ts, 73, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 73, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 73, 22))

if ("a" === testType) {
>testType : Symbol(testType, Decl(controlFlowAliasing2.ts, 86, 9))

this.test.name;
>this.test.name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
>this.test : Symbol(test, Decl(controlFlowAliasing2.ts, 73, 22))
>this : Symbol(this, Decl(controlFlowAliasing2.ts, 73, 15))
>test : Symbol(test, Decl(controlFlowAliasing2.ts, 73, 22))
>name : Symbol(TestA.name, Decl(controlFlowAliasing2.ts, 5, 12))
}
}

export {};

Loading