Skip to content

Commit 799d92b

Browse files
committed
TS: Fix self-reference check for alias types
1 parent c3c3faa commit 799d92b

File tree

1 file changed

+28
-1
lines changed

1 file changed

+28
-1
lines changed

javascript/extractor/lib/typescript/src/type_table.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ export class TypeTable {
450450
this.isInShallowTypeContext ? TypeExtractionState.PendingShallow : TypeExtractionState.PendingFull);
451451
// If the type is the self-type for a named type (not a generic instantiation of it),
452452
// emit the self-type binding for that type.
453-
if (content.startsWith("reference;") && !(isTypeReference(type) && type.target !== type)) {
453+
if (content.startsWith("reference;") && isTypeSelfReference(type)) {
454454
this.selfTypes.symbols.push(this.getSymbolId(type.aliasSymbol || type.symbol));
455455
this.selfTypes.selfTypes.push(id);
456456
}
@@ -1357,3 +1357,30 @@ function isFunctionTypeOrTypeAlias(declaration: ts.Declaration | undefined) {
13571357
if (declaration == null) return false;
13581358
return declaration.kind === ts.SyntaxKind.FunctionType || declaration.kind === ts.SyntaxKind.TypeAliasDeclaration;
13591359
}
1360+
1361+
/**
1362+
* Given a `type` whose type-string is known to be a `reference`, returns true if this is the self-type for the referenced type.
1363+
*
1364+
* For example, for `type Foo<R> = ...` this returns true if `type` is `Foo<R>`.
1365+
*/
1366+
function isTypeSelfReference(type: ts.Type) {
1367+
if (type.aliasSymbol != null) {
1368+
const { aliasTypeArguments } = type;
1369+
if (aliasTypeArguments == null) return true;
1370+
let declaration = type.aliasSymbol.declarations?.[0];
1371+
if (declaration == null || declaration.kind !== ts.SyntaxKind.TypeAliasDeclaration) return false;
1372+
let alias = declaration as ts.TypeAliasDeclaration;
1373+
for (let i = 0; i < aliasTypeArguments.length; ++i) {
1374+
if (aliasTypeArguments[i].symbol?.declarations?.[0] !== alias.typeParameters[i]) {
1375+
return false;
1376+
}
1377+
}
1378+
return true;
1379+
} else if (isTypeReference(type)) {
1380+
return type.target === type;
1381+
} else {
1382+
// Return true because we know we have mapped this type to kind `reference`, and in the cases
1383+
// not covered above (i.e. generic types) it is always a self-reference.
1384+
return true;
1385+
}
1386+
}

0 commit comments

Comments
 (0)