diff --git a/common/changes/@typespec/compiler/fix-alias-of-alias_2023-11-02-15-32.json b/common/changes/@typespec/compiler/fix-alias-of-alias_2023-11-02-15-32.json new file mode 100644 index 0000000000..5945164bd2 --- /dev/null +++ b/common/changes/@typespec/compiler/fix-alias-of-alias_2023-11-02-15-32.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@typespec/compiler", + "comment": "", + "type": "none" + } + ], + "packageName": "@typespec/compiler" +} \ No newline at end of file diff --git a/packages/compiler/src/core/checker.ts b/packages/compiler/src/core/checker.ts index 5bfaf2b144..f07dbe06a3 100644 --- a/packages/compiler/src/core/checker.ts +++ b/packages/compiler/src/core/checker.ts @@ -2344,12 +2344,19 @@ export function createChecker(program: Program): Checker { mapper: TypeMapper | undefined, options: SymbolResolutionOptions ): Sym | undefined { - const node = aliasSymbol.declarations[0]; - const targetNode = node.kind === SyntaxKind.AliasStatement ? node.value : node; - const sym = resolveTypeReferenceSymInternal(targetNode as any, mapper, options); - if (sym === undefined) { - return undefined; + let current = aliasSymbol; + while (current.flags & SymbolFlags.Alias) { + const node = current.declarations[0]; + const targetNode = node.kind === SyntaxKind.AliasStatement ? node.value : node; + const sym = resolveTypeReferenceSymInternal(targetNode as any, mapper, options); + if (sym === undefined) { + return undefined; + } + current = sym; } + const sym = current; + const node = aliasSymbol.declarations[0]; + const resolvedTargetNode = sym.declarations[0]; if (!options.checkTemplateTypes || !isTemplatedNode(resolvedTargetNode)) { return sym; diff --git a/packages/compiler/test/checker/references.test.ts b/packages/compiler/test/checker/references.test.ts index ed9a8ce722..2f2a102062 100644 --- a/packages/compiler/test/checker/references.test.ts +++ b/packages/compiler/test/checker/references.test.ts @@ -44,6 +44,18 @@ describe("compiler: references", () => { ref: "MyModel.x", })); + describe("member of alias of alias of model", () => + itCanReference({ + code: ` + model MyModel { + @test("target") x: string; + } + alias Alias1 = MyModel; + alias MyModelAlias = Alias1; + `, + ref: "MyModelAlias.x", + })); + describe("spread property from model defined before", () => itCanReference({ code: ` @@ -421,6 +433,18 @@ describe("compiler: references", () => { ref: "MyInterfaceAlias.operation", })); + describe("member of alias of alias of interface", () => + itCanReference({ + code: ` + interface MyInterface { + @test("target") operation(): void; + } + alias MyInterfaceAlias1 = MyInterface; + alias MyInterfaceAlias = MyInterfaceAlias1; + `, + ref: "MyInterfaceAlias.operation", + })); + describe("member of templated interface instance", () => itCanReference({ code: `