Skip to content

Commit 1e0466e

Browse files
authoredNov 23, 2023
feat: implement scoped type alias (#2806)
1 parent 153def6 commit 1e0466e

9 files changed

+802
-58
lines changed
 

‎src/compiler.ts

+34-18
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ import {
9393
PropertyPrototype,
9494
IndexSignature,
9595
File,
96-
mangleInternalName
96+
mangleInternalName,
97+
TypeDefinition
9798
} from "./program";
9899

99100
import {
@@ -180,7 +181,8 @@ import {
180181

181182
findDecorator,
182183
isTypeOmitted,
183-
Source
184+
Source,
185+
TypeDeclaration
184186
} from "./ast";
185187

186188
import {
@@ -1156,7 +1158,7 @@ export class Compiler extends DiagnosticEmitter {
11561158

11571159
// Resolve type if annotated
11581160
if (typeNode) {
1159-
let resolvedType = this.resolver.resolveType(typeNode, global.parent); // reports
1161+
let resolvedType = this.resolver.resolveType(typeNode, null, global.parent); // reports
11601162
if (!resolvedType) {
11611163
global.set(CommonFlags.Errored);
11621164
pendingElements.delete(global);
@@ -2238,13 +2240,7 @@ export class Compiler extends DiagnosticEmitter {
22382240
break;
22392241
}
22402242
case NodeKind.TypeDeclaration: {
2241-
// TODO: integrate inner type declaration into flow
2242-
this.error(
2243-
DiagnosticCode.Not_implemented_0,
2244-
statement.range,
2245-
"Inner type alias"
2246-
);
2247-
stmt = module.unreachable();
2243+
stmt = this.compileTypeDeclaration(<TypeDeclaration>statement);
22482244
break;
22492245
}
22502246
case NodeKind.Module: {
@@ -2305,6 +2301,24 @@ export class Compiler extends DiagnosticEmitter {
23052301
return this.module.flatten(stmts);
23062302
}
23072303

2304+
private compileTypeDeclaration(statement: TypeDeclaration): ExpressionRef {
2305+
let flow = this.currentFlow;
2306+
let name = statement.name.text;
2307+
let existedTypeAlias = flow.lookupScopedTypeAlias(name);
2308+
if (existedTypeAlias) {
2309+
this.errorRelated(
2310+
DiagnosticCode.Duplicate_identifier_0,
2311+
statement.range,
2312+
existedTypeAlias.declaration.range,
2313+
name
2314+
);
2315+
return this.module.unreachable();
2316+
}
2317+
let element = new TypeDefinition(name, flow.sourceFunction, statement, DecoratorFlags.None);
2318+
flow.addScopedTypeAlias(name, element);
2319+
return this.module.nop();
2320+
}
2321+
23082322
private compileBreakStatement(
23092323
statement: BreakStatement
23102324
): ExpressionRef {
@@ -2962,7 +2976,7 @@ export class Compiler extends DiagnosticEmitter {
29622976
let initializerNode = declaration.initializer;
29632977
if (typeNode) {
29642978
type = resolver.resolveType( // reports
2965-
typeNode,
2979+
typeNode, flow,
29662980
flow.sourceFunction,
29672981
cloneMap(flow.contextualTypeArguments)
29682982
);
@@ -3729,7 +3743,7 @@ export class Compiler extends DiagnosticEmitter {
37293743
case AssertionKind.As: {
37303744
let flow = this.currentFlow;
37313745
let toType = this.resolver.resolveType( // reports
3732-
assert(expression.toType),
3746+
assert(expression.toType), flow,
37333747
flow.sourceFunction,
37343748
cloneMap(flow.contextualTypeArguments)
37353749
);
@@ -6162,6 +6176,7 @@ export class Compiler extends DiagnosticEmitter {
61626176
typeArguments = this.resolver.resolveTypeArguments(
61636177
assert(typeParameterNodes),
61646178
typeArgumentNodes,
6179+
this.currentFlow,
61656180
this.currentFlow.sourceFunction.parent,
61666181
cloneMap(this.currentFlow.contextualTypeArguments), // don't update
61676182
expression
@@ -7085,7 +7100,7 @@ export class Compiler extends DiagnosticEmitter {
70857100
let parameterNode = parameterNodes[i];
70867101
if (!isTypeOmitted(parameterNode.type)) {
70877102
let resolvedType = this.resolver.resolveType(
7088-
parameterNode.type,
7103+
parameterNode.type, flow,
70897104
sourceFunction.parent,
70907105
contextualTypeArguments
70917106
);
@@ -7105,7 +7120,7 @@ export class Compiler extends DiagnosticEmitter {
71057120
let returnType = contextualSignature.returnType;
71067121
if (!isTypeOmitted(signatureNode.returnType)) {
71077122
let resolvedType = this.resolver.resolveType(
7108-
signatureNode.returnType,
7123+
signatureNode.returnType, flow,
71097124
sourceFunction.parent,
71107125
contextualTypeArguments
71117126
);
@@ -7135,7 +7150,7 @@ export class Compiler extends DiagnosticEmitter {
71357150
return module.unreachable();
71367151
}
71377152
let resolvedType = this.resolver.resolveType(
7138-
thisTypeNode,
7153+
thisTypeNode, flow,
71397154
sourceFunction.parent,
71407155
contextualTypeArguments
71417156
);
@@ -7522,7 +7537,7 @@ export class Compiler extends DiagnosticEmitter {
75227537
if (isType.kind == NodeKind.NamedType) {
75237538
let namedType = <NamedTypeNode>isType;
75247539
if (!(namedType.isNullable || namedType.hasTypeArguments)) {
7525-
let element = this.resolver.resolveTypeName(namedType.name, flow.sourceFunction, ReportMode.Swallow);
7540+
let element = this.resolver.resolveTypeName(namedType.name, flow, flow.sourceFunction, ReportMode.Swallow);
75267541
if (element && element.kind == ElementKind.ClassPrototype) {
75277542
let prototype = <ClassPrototype>element;
75287543
if (prototype.is(CommonFlags.Generic)) {
@@ -7534,7 +7549,7 @@ export class Compiler extends DiagnosticEmitter {
75347549

75357550
// Fall back to `instanceof TYPE`
75367551
let expectedType = this.resolver.resolveType(
7537-
expression.isType,
7552+
expression.isType, flow,
75387553
flow.sourceFunction,
75397554
cloneMap(flow.contextualTypeArguments)
75407555
);
@@ -8686,7 +8701,7 @@ export class Compiler extends DiagnosticEmitter {
86868701
let flow = this.currentFlow;
86878702

86888703
// obtain the class being instantiated
8689-
let target = this.resolver.resolveTypeName(expression.typeName, flow.sourceFunction);
8704+
let target = this.resolver.resolveTypeName(expression.typeName, flow, flow.sourceFunction);
86908705
if (!target) return module.unreachable();
86918706
if (target.kind != ElementKind.ClassPrototype) {
86928707
this.error(
@@ -8722,6 +8737,7 @@ export class Compiler extends DiagnosticEmitter {
87228737
classInstance = this.resolver.resolveClassInclTypeArguments(
87238738
classPrototype,
87248739
typeArguments,
8740+
flow,
87258741
flow.sourceFunction.parent, // relative to caller
87268742
cloneMap(flow.contextualTypeArguments),
87278743
expression

‎src/flow.ts

+36-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ import {
3131
TypedElement,
3232
mangleInternalName,
3333
Property,
34-
PropertyPrototype
34+
PropertyPrototype,
35+
TypeDefinition
3536
} from "./program";
3637

3738
import {
@@ -250,6 +251,8 @@ export class Flow {
250251
breakLabel: string | null = null;
251252
/** Scoped local variables. */
252253
scopedLocals: Map<string,Local> | null = null;
254+
/** Scoped type alias. */
255+
scopedTypeAlias: Map<string,TypeDefinition> | null = null;
253256
/** Local flags. */
254257
localFlags: LocalFlags[] = [];
255258
/** Field flags on `this`. Constructors only. */
@@ -405,6 +408,38 @@ export class Flow {
405408
falseFlows.set(condExpr, falseFlow);
406409
}
407410

411+
addScopedTypeAlias(name: string, definition: TypeDefinition): void {
412+
let scopedTypeAlias = this.scopedTypeAlias;
413+
if (!scopedTypeAlias) this.scopedTypeAlias = scopedTypeAlias = new Map();
414+
scopedTypeAlias.set(name, definition);
415+
}
416+
417+
lookupScopedTypeAlias(name: string): TypeDefinition | null {
418+
let current: Flow | null = this;
419+
do {
420+
let scopedTypeAlias = current.scopedTypeAlias;
421+
if (scopedTypeAlias && scopedTypeAlias.has(name)) {
422+
return assert(scopedTypeAlias.get(name));
423+
}
424+
current = current.parent;
425+
} while (current);
426+
return null;
427+
}
428+
429+
lookupTypeAlias(name: string): TypeDefinition | null {
430+
let definition: TypeDefinition | null = null;
431+
if (definition = this.lookupScopedTypeAlias(name)) return definition;
432+
433+
let sourceParent = this.sourceFunction.parent;
434+
if (sourceParent.kind == ElementKind.Function) {
435+
// lookup parent function.
436+
let parentFunction = <Function>sourceParent;
437+
return parentFunction.flow.lookupTypeAlias(name);
438+
}
439+
440+
return null;
441+
}
442+
408443
/** Gets a free temporary local of the specified type. */
409444
getTempLocal(type: Type): Local {
410445
let local = this.targetFunction.addLocal(type);

‎src/program.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1308,7 +1308,7 @@ export class Program extends DiagnosticEmitter {
13081308
for (let i = 0, k = queuedExtends.length; i < k; ++i) {
13091309
let thisPrototype = queuedExtends[i];
13101310
let extendsNode = assert(thisPrototype.extendsNode); // must be present if in queuedExtends
1311-
let baseElement = resolver.resolveTypeName(extendsNode.name, thisPrototype.parent);
1311+
let baseElement = resolver.resolveTypeName(extendsNode.name, null, thisPrototype.parent);
13121312
if (!baseElement) continue;
13131313
if (thisPrototype.kind == ElementKind.ClassPrototype) {
13141314
if (baseElement.kind == ElementKind.ClassPrototype) {
@@ -1405,7 +1405,7 @@ export class Program extends DiagnosticEmitter {
14051405
let implementsNodes = assert(thisPrototype.implementsNodes); // must be present if in queuedImplements
14061406
for (let j = 0, l = implementsNodes.length; j < l; ++j) {
14071407
let implementsNode = implementsNodes[j];
1408-
let interfaceElement = resolver.resolveTypeName(implementsNode.name, thisPrototype.parent);
1408+
let interfaceElement = resolver.resolveTypeName(implementsNode.name, null, thisPrototype.parent);
14091409
if (!interfaceElement) continue;
14101410
if (interfaceElement.kind == ElementKind.InterfacePrototype) {
14111411
let interfacePrototype = <InterfacePrototype>interfaceElement;
@@ -3383,7 +3383,7 @@ export class TypeDefinition extends TypedElement {
33833383
constructor(
33843384
/** Simple name. */
33853385
name: string,
3386-
/** Parent element, usually a file or namespace. */
3386+
/** Parent element. */
33873387
parent: Element,
33883388
/** Declaration reference. */
33893389
declaration: TypeDeclaration,

‎src/resolver.ts

+49-27
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ export class Resolver extends DiagnosticEmitter {
142142
resolveType(
143143
/** The type to resolve. */
144144
node: TypeNode,
145+
/** The flow */
146+
flow: Flow | null,
145147
/** Contextual element. */
146148
ctxElement: Element,
147149
/** Contextual types, i.e. `T`. */
@@ -160,21 +162,11 @@ export class Resolver extends DiagnosticEmitter {
160162
let resolved: Type | null = null;
161163
switch (node.kind) {
162164
case NodeKind.NamedType: {
163-
resolved = this.resolveNamedType(
164-
<NamedTypeNode>node,
165-
ctxElement,
166-
ctxTypes,
167-
reportMode
168-
);
165+
resolved = this.resolveNamedType(<NamedTypeNode>node, flow, ctxElement, ctxTypes, reportMode);
169166
break;
170167
}
171168
case NodeKind.FunctionType: {
172-
resolved = this.resolveFunctionType(
173-
<FunctionTypeNode>node,
174-
ctxElement,
175-
ctxTypes,
176-
reportMode
177-
);
169+
resolved = this.resolveFunctionType(<FunctionTypeNode>node, flow, ctxElement, ctxTypes, reportMode);
178170
break;
179171
}
180172
default: assert(false);
@@ -187,6 +179,8 @@ export class Resolver extends DiagnosticEmitter {
187179
private resolveNamedType(
188180
/** The type to resolve. */
189181
node: NamedTypeNode,
182+
/** The flow */
183+
flow: Flow | null,
190184
/** Contextual element. */
191185
ctxElement: Element,
192186
/** Contextual types, i.e. `T`. */
@@ -225,7 +219,7 @@ export class Resolver extends DiagnosticEmitter {
225219
}
226220

227221
// Look up in context
228-
let element = this.resolveTypeName(nameNode, ctxElement, reportMode);
222+
let element = this.resolveTypeName(nameNode, flow, ctxElement, reportMode);
229223
if (!element) return null;
230224

231225
// Use shadow type if present (i.e. namespace sharing a type)
@@ -264,6 +258,7 @@ export class Resolver extends DiagnosticEmitter {
264258
let instance = this.resolveClassInclTypeArguments(
265259
<ClassPrototype>element,
266260
typeArgumentNodes,
261+
flow,
267262
ctxElement,
268263
cloneMap(ctxTypes), // don't inherit
269264
node,
@@ -318,6 +313,7 @@ export class Resolver extends DiagnosticEmitter {
318313
typeArguments = this.resolveTypeArguments(
319314
typeParameterNodes,
320315
typeArgumentNodes,
316+
flow,
321317
ctxElement,
322318
ctxTypes = cloneMap(ctxTypes), // update
323319
node,
@@ -332,6 +328,7 @@ export class Resolver extends DiagnosticEmitter {
332328
}
333329
let type = this.resolveType(
334330
typeDefinition.typeNode,
331+
flow,
335332
element,
336333
ctxTypes,
337334
reportMode
@@ -361,6 +358,8 @@ export class Resolver extends DiagnosticEmitter {
361358
private resolveFunctionType(
362359
/** The type to resolve. */
363360
node: FunctionTypeNode,
361+
/** The flow */
362+
flow: Flow | null,
364363
/** Contextual element. */
365364
ctxElement: Element,
366365
/** Contextual types, i.e. `T`. */
@@ -373,6 +372,7 @@ export class Resolver extends DiagnosticEmitter {
373372
if (explicitThisType) {
374373
thisType = this.resolveType(
375374
explicitThisType,
375+
flow,
376376
ctxElement,
377377
ctxTypes,
378378
reportMode
@@ -409,6 +409,7 @@ export class Resolver extends DiagnosticEmitter {
409409
}
410410
let parameterType = this.resolveType(
411411
parameterTypeNode,
412+
flow,
412413
ctxElement,
413414
ctxTypes,
414415
reportMode
@@ -429,6 +430,7 @@ export class Resolver extends DiagnosticEmitter {
429430
} else {
430431
returnType = this.resolveType(
431432
returnTypeNode,
433+
flow,
432434
ctxElement,
433435
ctxTypes,
434436
reportMode
@@ -451,7 +453,7 @@ export class Resolver extends DiagnosticEmitter {
451453
): Type | null {
452454
const typeArgumentNode = this.ensureOneTypeArgument(node, reportMode);
453455
if (!typeArgumentNode) return null;
454-
let typeArgument = this.resolveType(typeArgumentNode, ctxElement, ctxTypes, reportMode);
456+
let typeArgument = this.resolveType(typeArgumentNode, null, ctxElement, ctxTypes, reportMode);
455457
if (!typeArgument) return null;
456458
switch (typeArgument.kind) {
457459
case TypeKind.I8:
@@ -486,7 +488,7 @@ export class Resolver extends DiagnosticEmitter {
486488
): Type | null {
487489
const typeArgumentNode = this.ensureOneTypeArgument(node, reportMode);
488490
if (!typeArgumentNode) return null;
489-
let typeArgument = this.resolveType(typeArgumentNode, ctxElement, ctxTypes, reportMode);
491+
let typeArgument = this.resolveType(typeArgumentNode, null, ctxElement, ctxTypes, reportMode);
490492
if (!typeArgument) return null;
491493
let classReference = typeArgument.classReference;
492494
if (!classReference) {
@@ -530,7 +532,7 @@ export class Resolver extends DiagnosticEmitter {
530532
): Type | null {
531533
const typeArgumentNode = this.ensureOneTypeArgument(node, reportMode);
532534
if (!typeArgumentNode) return null;
533-
let typeArgument = this.resolveType(typeArgumentNode, ctxElement, ctxTypes, reportMode);
535+
let typeArgument = this.resolveType(typeArgumentNode, null, ctxElement, ctxTypes, reportMode);
534536
if (!typeArgument) return null;
535537
let classReference = typeArgument.getClassOrWrapper(this.program);
536538
if (classReference) {
@@ -558,7 +560,7 @@ export class Resolver extends DiagnosticEmitter {
558560
): Type | null {
559561
const typeArgumentNode = this.ensureOneTypeArgument(node, reportMode);
560562
if (!typeArgumentNode) return null;
561-
let typeArgument = this.resolveType(typeArgumentNode, ctxElement, ctxTypes, reportMode);
563+
let typeArgument = this.resolveType(typeArgumentNode, null, ctxElement, ctxTypes, reportMode);
562564
if (!typeArgument) return null;
563565
let signatureReference = typeArgument.getSignature();
564566
if (signatureReference) return signatureReference.returnType;
@@ -583,7 +585,7 @@ export class Resolver extends DiagnosticEmitter {
583585
): Type | null {
584586
const typeArgumentNode = this.ensureOneTypeArgument(node, reportMode);
585587
if (!typeArgumentNode) return null;
586-
let typeArgument = this.resolveType(typeArgumentNode, ctxElement, ctxTypes, reportMode);
588+
let typeArgument = this.resolveType(typeArgumentNode, null, ctxElement, ctxTypes, reportMode);
587589
if (!typeArgument) return null;
588590
if (!typeArgument.isNullableReference) return typeArgument;
589591
return typeArgument.nonNullableType;
@@ -593,12 +595,16 @@ export class Resolver extends DiagnosticEmitter {
593595
resolveTypeName(
594596
/** The type name to resolve. */
595597
node: TypeName,
598+
/** The flow */
599+
flow: Flow | null,
596600
/** Contextual element. */
597601
ctxElement: Element,
598602
/** How to proceed with eventual diagnostics. */
599603
reportMode: ReportMode = ReportMode.Report
600604
): Element | null {
601-
let element = ctxElement.lookup(node.identifier.text, true);
605+
let element: Element | null = null;
606+
if (flow) element = flow.lookupTypeAlias(node.identifier.text);
607+
if (!element) element = ctxElement.lookup(node.identifier.text, true);
602608
if (!element) {
603609
if (reportMode == ReportMode.Report) {
604610
this.error(
@@ -632,6 +638,8 @@ export class Resolver extends DiagnosticEmitter {
632638
typeParameters: TypeParameterNode[],
633639
/** Type argument nodes provided. */
634640
typeArgumentNodes: TypeNode[] | null,
641+
/** Flow */
642+
flow: Flow | null,
635643
/** Contextual element. */
636644
ctxElement: Element,
637645
/** Contextual types, i.e. `T`. Updated in place with the new set of contextual types. */
@@ -641,9 +649,8 @@ export class Resolver extends DiagnosticEmitter {
641649
/** How to proceed with eventual diagnostics. */
642650
reportMode: ReportMode = ReportMode.Report
643651
): Type[] | null {
644-
var
645-
minParameterCount = 0,
646-
maxParameterCount = 0;
652+
let minParameterCount = 0;
653+
let maxParameterCount = 0;
647654
for (let i = 0, k = typeParameters.length; i < k; ++i) {
648655
if (!typeParameters[i].defaultType) ++minParameterCount;
649656
++maxParameterCount;
@@ -672,12 +679,14 @@ export class Resolver extends DiagnosticEmitter {
672679
let type = i < argumentCount
673680
? this.resolveType( // reports
674681
typeArgumentNodes![i],
682+
flow,
675683
ctxElement,
676684
oldCtxTypes, // update
677685
reportMode
678686
)
679687
: this.resolveType( // reports
680688
assert(typeParameters[i].defaultType),
689+
flow,
681690
ctxElement,
682691
cloneMap(ctxTypes), // don't update
683692
reportMode
@@ -796,6 +805,7 @@ export class Resolver extends DiagnosticEmitter {
796805
}
797806
let resolvedDefaultType = this.resolveType(
798807
defaultType,
808+
null,
799809
prototype,
800810
defaultTypeContextualTypeArguments,
801811
reportMode
@@ -846,7 +856,7 @@ export class Resolver extends DiagnosticEmitter {
846856
if (typeArgumentNodes && typeArgumentNodes.length > 0) { // foo<T>(bar: Array<T>)
847857
let classReference = type.classReference;
848858
if (classReference) {
849-
let classPrototype = this.resolveTypeName(namedTypeNode.name, ctxElement);
859+
let classPrototype = this.resolveTypeName(namedTypeNode.name, null, ctxElement);
850860
if (!classPrototype || classPrototype.kind != ElementKind.ClassPrototype) return;
851861
if (classReference.prototype == <ClassPrototype>classPrototype) {
852862
let typeArguments = classReference.typeArguments;
@@ -1306,7 +1316,7 @@ export class Resolver extends DiagnosticEmitter {
13061316
if (global.is(CommonFlags.Resolved)) return true;
13071317
let typeNode = global.typeNode;
13081318
let type = typeNode
1309-
? this.resolveType(typeNode, global.parent, null, reportMode)
1319+
? this.resolveType(typeNode, null, global.parent, null, reportMode)
13101320
: this.resolveExpression(
13111321
assert(global.initializerNode),
13121322
global.file.startFunction.flow,
@@ -1424,7 +1434,7 @@ export class Resolver extends DiagnosticEmitter {
14241434
let shadowType = target.shadowType;
14251435
if (shadowType) {
14261436
if (!shadowType.is(CommonFlags.Resolved)) {
1427-
let resolvedType = this.resolveType(shadowType.typeNode, shadowType.parent, null, reportMode);
1437+
let resolvedType = this.resolveType(shadowType.typeNode, null, shadowType.parent, null, reportMode);
14281438
if (resolvedType) shadowType.setType(resolvedType);
14291439
}
14301440
let classReference = shadowType.type.classReference;
@@ -1708,6 +1718,7 @@ export class Resolver extends DiagnosticEmitter {
17081718
case AssertionKind.Prefix: {
17091719
let type = this.resolveType(
17101720
assert(node.toType), // must be set if not NONNULL
1721+
null,
17111722
ctxFlow.sourceFunction,
17121723
ctxFlow.contextualTypeArguments,
17131724
reportMode
@@ -1764,6 +1775,7 @@ export class Resolver extends DiagnosticEmitter {
17641775
case AssertionKind.Prefix: {
17651776
return this.resolveType(
17661777
assert(node.toType),
1778+
null,
17671779
ctxFlow.sourceFunction,
17681780
ctxFlow.contextualTypeArguments,
17691781
reportMode
@@ -2659,12 +2671,13 @@ export class Resolver extends DiagnosticEmitter {
26592671
/** How to proceed with eventual diagnostics. */
26602672
reportMode: ReportMode = ReportMode.Report
26612673
): Element | null {
2662-
let element = this.resolveTypeName(node.typeName, ctxFlow.sourceFunction, reportMode);
2674+
let element = this.resolveTypeName(node.typeName, ctxFlow, ctxFlow.sourceFunction, reportMode);
26632675
if (!element) return null;
26642676
if (element.kind == ElementKind.ClassPrototype) {
26652677
return this.resolveClassInclTypeArguments(
26662678
<ClassPrototype>element,
26672679
node.typeArguments,
2680+
ctxFlow,
26682681
ctxFlow.sourceFunction,
26692682
cloneMap(ctxFlow.contextualTypeArguments),
26702683
node,
@@ -2744,7 +2757,7 @@ export class Resolver extends DiagnosticEmitter {
27442757
const declaration = node.declaration;
27452758
const signature = declaration.signature;
27462759
const body = declaration.body;
2747-
let functionType = this.resolveType(signature, ctxFlow.sourceFunction, ctxFlow.contextualTypeArguments, reportMode);
2760+
let functionType = this.resolveType(signature, null, ctxFlow.sourceFunction, ctxFlow.contextualTypeArguments, reportMode);
27482761
if (
27492762
functionType &&
27502763
declaration.arrowKind != ArrowKind.None &&
@@ -2843,6 +2856,7 @@ export class Resolver extends DiagnosticEmitter {
28432856
if (explicitThisType) {
28442857
thisType = this.resolveType(
28452858
explicitThisType,
2859+
null,
28462860
prototype.parent, // relative to function
28472861
ctxTypes,
28482862
reportMode
@@ -2876,6 +2890,7 @@ export class Resolver extends DiagnosticEmitter {
28762890
}
28772891
let parameterType = this.resolveType(
28782892
typeNode,
2893+
null,
28792894
prototype.parent, // relative to function
28802895
ctxTypes,
28812896
reportMode
@@ -2912,6 +2927,7 @@ export class Resolver extends DiagnosticEmitter {
29122927
}
29132928
let type = this.resolveType(
29142929
typeNode,
2930+
null,
29152931
prototype.parent, // relative to function
29162932
ctxTypes,
29172933
reportMode
@@ -3026,6 +3042,7 @@ export class Resolver extends DiagnosticEmitter {
30263042
resolvedTypeArguments = this.resolveTypeArguments( // reports
30273043
assert(prototype.typeParameterNodes),
30283044
typeArgumentNodes,
3045+
null,
30293046
ctxElement,
30303047
ctxTypes, // update
30313048
reportNode,
@@ -3174,6 +3191,7 @@ export class Resolver extends DiagnosticEmitter {
31743191
let base = this.resolveClassInclTypeArguments(
31753192
basePrototype,
31763193
extendsNode.typeArguments,
3194+
null,
31773195
prototype.parent, // relative to derived class
31783196
cloneMap(ctxTypes), // don't inherit
31793197
extendsNode,
@@ -3214,6 +3232,7 @@ export class Resolver extends DiagnosticEmitter {
32143232
let iface = this.resolveClassInclTypeArguments(
32153233
interfacePrototype,
32163234
implementsNode.typeArguments,
3235+
null,
32173236
prototype.parent,
32183237
cloneMap(ctxTypes),
32193238
implementsNode,
@@ -3610,6 +3629,8 @@ export class Resolver extends DiagnosticEmitter {
36103629
prototype: ClassPrototype,
36113630
/** Type arguments provided to be resolved. */
36123631
typeArgumentNodes: TypeNode[] | null,
3632+
/** Flow of {@link typeArgumentNodes} */
3633+
flow: Flow | null,
36133634
/** Contextual element. */
36143635
ctxElement: Element,
36153636
/** Contextual types, i.e. `T`. */
@@ -3626,6 +3647,7 @@ export class Resolver extends DiagnosticEmitter {
36263647
resolvedTypeArguments = this.resolveTypeArguments( // reports
36273648
assert(prototype.typeParameterNodes), // must be present if generic
36283649
typeArgumentNodes,
3650+
flow,
36293651
ctxElement,
36303652
ctxTypes, // update
36313653
reportNode,

‎tests/compiler/typealias-errors.json

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"asc_flags": [
3+
],
4+
"stderr": [
5+
"TS2300: Duplicate identifier 'A'."
6+
]
7+
}

‎tests/compiler/typealias-errors.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export function DuplicateTypeAlias(): void {
2+
type A = i32;
3+
type A = i32;
4+
}

‎tests/compiler/typealias.debug.wat

+363-7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,371 @@
11
(module
2-
(type $0 (func (param i32) (result i32)))
3-
(global $~lib/memory/__data_end i32 (i32.const 8))
4-
(global $~lib/memory/__stack_pointer (mut i32) (i32.const 32776))
5-
(global $~lib/memory/__heap_base i32 (i32.const 32776))
6-
(memory $0 0)
7-
(table $0 1 1 funcref)
8-
(elem $0 (i32.const 1))
2+
(type $0 (func))
3+
(type $1 (func (param i32) (result i32)))
4+
(type $2 (func (param i32 i32 i32 i32 i32) (result i32)))
5+
(type $3 (func (param i32 i32 i32 i32)))
6+
(type $4 (func (param i32 i32) (result i32)))
7+
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
8+
(global $~lib/shared/runtime/Runtime.Stub i32 (i32.const 0))
9+
(global $~lib/shared/runtime/Runtime.Minimal i32 (i32.const 1))
10+
(global $~lib/shared/runtime/Runtime.Incremental i32 (i32.const 2))
11+
(global $~lib/native/ASC_SHRINK_LEVEL i32 (i32.const 0))
12+
(global $~argumentsLength (mut i32) (i32.const 0))
13+
(global $~lib/memory/__data_end i32 (i32.const 156))
14+
(global $~lib/memory/__stack_pointer (mut i32) (i32.const 32924))
15+
(global $~lib/memory/__heap_base i32 (i32.const 32924))
16+
(memory $0 1)
17+
(data $0 (i32.const 12) "\1c\00\00\00\00\00\00\00\00\00\00\00\02\00\00\00\06\00\00\00i\006\004\00\00\00\00\00\00\00")
18+
(data $1 (i32.const 44) ",\00\00\00\00\00\00\00\00\00\00\00\02\00\00\00\18\00\00\00t\00y\00p\00e\00a\00l\00i\00a\00s\00.\00t\00s\00\00\00\00\00")
19+
(data $2 (i32.const 92) "\1c\00\00\00\00\00\00\00\00\00\00\00\02\00\00\00\06\00\00\00f\006\004\00\00\00\00\00\00\00")
20+
(data $3 (i32.const 124) "\1c\00\00\00\00\00\00\00\00\00\00\00\04\00\00\00\08\00\00\00\01\00\00\00\00\00\00\00\00\00\00\00")
21+
(table $0 2 2 funcref)
22+
(elem $0 (i32.const 1) $typealias/outer_function~inner_function)
923
(export "alias" (func $typealias/alias))
1024
(export "memory" (memory $0))
25+
(start $~start)
26+
(func $~lib/rt/common/OBJECT#get:rtSize (param $this i32) (result i32)
27+
local.get $this
28+
i32.load offset=16
29+
)
30+
(func $~lib/string/String#get:length (param $this i32) (result i32)
31+
local.get $this
32+
i32.const 20
33+
i32.sub
34+
call $~lib/rt/common/OBJECT#get:rtSize
35+
i32.const 1
36+
i32.shr_u
37+
return
38+
)
39+
(func $~lib/util/string/compareImpl (param $str1 i32) (param $index1 i32) (param $str2 i32) (param $index2 i32) (param $len i32) (result i32)
40+
(local $ptr1 i32)
41+
(local $ptr2 i32)
42+
(local $7 i32)
43+
(local $a i32)
44+
(local $b i32)
45+
local.get $str1
46+
local.get $index1
47+
i32.const 1
48+
i32.shl
49+
i32.add
50+
local.set $ptr1
51+
local.get $str2
52+
local.get $index2
53+
i32.const 1
54+
i32.shl
55+
i32.add
56+
local.set $ptr2
57+
i32.const 0
58+
i32.const 2
59+
i32.lt_s
60+
drop
61+
local.get $len
62+
i32.const 4
63+
i32.ge_u
64+
if (result i32)
65+
local.get $ptr1
66+
i32.const 7
67+
i32.and
68+
local.get $ptr2
69+
i32.const 7
70+
i32.and
71+
i32.or
72+
i32.eqz
73+
else
74+
i32.const 0
75+
end
76+
if
77+
block $do-break|0
78+
loop $do-loop|0
79+
local.get $ptr1
80+
i64.load
81+
local.get $ptr2
82+
i64.load
83+
i64.ne
84+
if
85+
br $do-break|0
86+
end
87+
local.get $ptr1
88+
i32.const 8
89+
i32.add
90+
local.set $ptr1
91+
local.get $ptr2
92+
i32.const 8
93+
i32.add
94+
local.set $ptr2
95+
local.get $len
96+
i32.const 4
97+
i32.sub
98+
local.set $len
99+
local.get $len
100+
i32.const 4
101+
i32.ge_u
102+
br_if $do-loop|0
103+
end
104+
end
105+
end
106+
loop $while-continue|1
107+
local.get $len
108+
local.tee $7
109+
i32.const 1
110+
i32.sub
111+
local.set $len
112+
local.get $7
113+
if
114+
local.get $ptr1
115+
i32.load16_u
116+
local.set $a
117+
local.get $ptr2
118+
i32.load16_u
119+
local.set $b
120+
local.get $a
121+
local.get $b
122+
i32.ne
123+
if
124+
local.get $a
125+
local.get $b
126+
i32.sub
127+
return
128+
end
129+
local.get $ptr1
130+
i32.const 2
131+
i32.add
132+
local.set $ptr1
133+
local.get $ptr2
134+
i32.const 2
135+
i32.add
136+
local.set $ptr2
137+
br $while-continue|1
138+
end
139+
end
140+
i32.const 0
141+
return
142+
)
143+
(func $typealias/generic_type_alias
144+
i32.const 5
145+
i32.const 5
146+
i32.eq
147+
drop
148+
)
149+
(func $typealias/alias_in_type_arguments
150+
i32.const 6
151+
i32.const 6
152+
i32.eq
153+
drop
154+
)
155+
(func $start:typealias
156+
call $typealias/outer_function
157+
call $typealias/generic_type_alias
158+
call $typealias/alias_in_type_arguments
159+
)
11160
(func $typealias/alias (param $a i32) (result i32)
12161
local.get $a
13162
return
14163
)
164+
(func $~start
165+
call $start:typealias
166+
)
167+
(func $~stack_check
168+
global.get $~lib/memory/__stack_pointer
169+
global.get $~lib/memory/__data_end
170+
i32.lt_s
171+
if
172+
i32.const 32944
173+
i32.const 32992
174+
i32.const 1
175+
i32.const 1
176+
call $~lib/builtins/abort
177+
unreachable
178+
end
179+
)
180+
(func $~lib/string/String.__eq (param $left i32) (param $right i32) (result i32)
181+
(local $leftLength i32)
182+
(local $3 i32)
183+
global.get $~lib/memory/__stack_pointer
184+
i32.const 8
185+
i32.sub
186+
global.set $~lib/memory/__stack_pointer
187+
call $~stack_check
188+
global.get $~lib/memory/__stack_pointer
189+
i64.const 0
190+
i64.store
191+
local.get $left
192+
local.get $right
193+
i32.eq
194+
if
195+
i32.const 1
196+
local.set $3
197+
global.get $~lib/memory/__stack_pointer
198+
i32.const 8
199+
i32.add
200+
global.set $~lib/memory/__stack_pointer
201+
local.get $3
202+
return
203+
end
204+
local.get $left
205+
i32.const 0
206+
i32.eq
207+
if (result i32)
208+
i32.const 1
209+
else
210+
local.get $right
211+
i32.const 0
212+
i32.eq
213+
end
214+
if
215+
i32.const 0
216+
local.set $3
217+
global.get $~lib/memory/__stack_pointer
218+
i32.const 8
219+
i32.add
220+
global.set $~lib/memory/__stack_pointer
221+
local.get $3
222+
return
223+
end
224+
local.get $left
225+
local.set $3
226+
global.get $~lib/memory/__stack_pointer
227+
local.get $3
228+
i32.store
229+
local.get $3
230+
call $~lib/string/String#get:length
231+
local.set $leftLength
232+
local.get $leftLength
233+
local.get $right
234+
local.set $3
235+
global.get $~lib/memory/__stack_pointer
236+
local.get $3
237+
i32.store
238+
local.get $3
239+
call $~lib/string/String#get:length
240+
i32.ne
241+
if
242+
i32.const 0
243+
local.set $3
244+
global.get $~lib/memory/__stack_pointer
245+
i32.const 8
246+
i32.add
247+
global.set $~lib/memory/__stack_pointer
248+
local.get $3
249+
return
250+
end
251+
local.get $left
252+
local.set $3
253+
global.get $~lib/memory/__stack_pointer
254+
local.get $3
255+
i32.store
256+
local.get $3
257+
i32.const 0
258+
local.get $right
259+
local.set $3
260+
global.get $~lib/memory/__stack_pointer
261+
local.get $3
262+
i32.store offset=4
263+
local.get $3
264+
i32.const 0
265+
local.get $leftLength
266+
call $~lib/util/string/compareImpl
267+
i32.eqz
268+
local.set $3
269+
global.get $~lib/memory/__stack_pointer
270+
i32.const 8
271+
i32.add
272+
global.set $~lib/memory/__stack_pointer
273+
local.get $3
274+
return
275+
)
276+
(func $typealias/outer_function~inner_function
277+
(local $alias f64)
278+
(local $1 i32)
279+
global.get $~lib/memory/__stack_pointer
280+
i32.const 8
281+
i32.sub
282+
global.set $~lib/memory/__stack_pointer
283+
call $~stack_check
284+
global.get $~lib/memory/__stack_pointer
285+
i64.const 0
286+
i64.store
287+
f64.const 1
288+
local.set $alias
289+
i32.const 112
290+
local.set $1
291+
global.get $~lib/memory/__stack_pointer
292+
local.get $1
293+
i32.store
294+
local.get $1
295+
i32.const 112
296+
local.set $1
297+
global.get $~lib/memory/__stack_pointer
298+
local.get $1
299+
i32.store offset=4
300+
local.get $1
301+
call $~lib/string/String.__eq
302+
i32.eqz
303+
if
304+
i32.const 0
305+
i32.const 64
306+
i32.const 17
307+
i32.const 5
308+
call $~lib/builtins/abort
309+
unreachable
310+
end
311+
global.get $~lib/memory/__stack_pointer
312+
i32.const 8
313+
i32.add
314+
global.set $~lib/memory/__stack_pointer
315+
)
316+
(func $typealias/outer_function
317+
(local $alias i64)
318+
(local $inner_function i32)
319+
(local $2 i32)
320+
global.get $~lib/memory/__stack_pointer
321+
i32.const 12
322+
i32.sub
323+
global.set $~lib/memory/__stack_pointer
324+
call $~stack_check
325+
global.get $~lib/memory/__stack_pointer
326+
i64.const 0
327+
i64.store
328+
global.get $~lib/memory/__stack_pointer
329+
i32.const 0
330+
i32.store offset=8
331+
i64.const 1
332+
local.set $alias
333+
i32.const 32
334+
local.set $2
335+
global.get $~lib/memory/__stack_pointer
336+
local.get $2
337+
i32.store
338+
local.get $2
339+
i32.const 32
340+
local.set $2
341+
global.get $~lib/memory/__stack_pointer
342+
local.get $2
343+
i32.store offset=4
344+
local.get $2
345+
call $~lib/string/String.__eq
346+
i32.eqz
347+
if
348+
i32.const 0
349+
i32.const 64
350+
i32.const 13
351+
i32.const 3
352+
call $~lib/builtins/abort
353+
unreachable
354+
end
355+
global.get $~lib/memory/__stack_pointer
356+
i32.const 144
357+
local.tee $inner_function
358+
i32.store offset=8
359+
local.get $inner_function
360+
drop
361+
i32.const 0
362+
global.set $~argumentsLength
363+
local.get $inner_function
364+
i32.load
365+
call_indirect (type $0)
366+
global.get $~lib/memory/__stack_pointer
367+
i32.const 12
368+
i32.add
369+
global.set $~lib/memory/__stack_pointer
370+
)
15371
)

‎tests/compiler/typealias.release.wat

+280-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,287 @@
11
(module
2-
(type $0 (func (param i32) (result i32)))
3-
(memory $0 0)
2+
(type $0 (func))
3+
(type $1 (func (param i32 i32 i32 i32)))
4+
(type $2 (func (param i32) (result i32)))
5+
(type $3 (func (param i32 i32) (result i32)))
6+
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
7+
(global $~lib/memory/__stack_pointer (mut i32) (i32.const 33948))
8+
(memory $0 1)
9+
(data $0 (i32.const 1036) "\1c")
10+
(data $0.1 (i32.const 1048) "\02\00\00\00\06\00\00\00i\006\004")
11+
(data $1 (i32.const 1068) ",")
12+
(data $1.1 (i32.const 1080) "\02\00\00\00\18\00\00\00t\00y\00p\00e\00a\00l\00i\00a\00s\00.\00t\00s")
13+
(data $2 (i32.const 1116) "\1c")
14+
(data $2.1 (i32.const 1128) "\02\00\00\00\06\00\00\00f\006\004")
15+
(data $3 (i32.const 1148) "\1c")
16+
(data $3.1 (i32.const 1160) "\04\00\00\00\08\00\00\00\01")
17+
(table $0 2 2 funcref)
18+
(elem $0 (i32.const 1) $typealias/outer_function~inner_function)
419
(export "alias" (func $typealias/alias))
520
(export "memory" (memory $0))
21+
(start $~start)
622
(func $typealias/alias (param $0 i32) (result i32)
723
local.get $0
824
)
25+
(func $~start
26+
(local $0 i32)
27+
global.get $~lib/memory/__stack_pointer
28+
i32.const 12
29+
i32.sub
30+
global.set $~lib/memory/__stack_pointer
31+
global.get $~lib/memory/__stack_pointer
32+
i32.const 1180
33+
i32.lt_s
34+
if
35+
i32.const 33968
36+
i32.const 34016
37+
i32.const 1
38+
i32.const 1
39+
call $~lib/builtins/abort
40+
unreachable
41+
end
42+
global.get $~lib/memory/__stack_pointer
43+
local.tee $0
44+
i64.const 0
45+
i64.store
46+
local.get $0
47+
i32.const 0
48+
i32.store offset=8
49+
local.get $0
50+
i32.const 1056
51+
i32.store
52+
local.get $0
53+
i32.const 1056
54+
i32.store offset=4
55+
i32.const 1056
56+
i32.const 1056
57+
call $~lib/string/String.__eq
58+
i32.eqz
59+
if
60+
i32.const 0
61+
i32.const 1088
62+
i32.const 13
63+
i32.const 3
64+
call $~lib/builtins/abort
65+
unreachable
66+
end
67+
global.get $~lib/memory/__stack_pointer
68+
i32.const 1168
69+
i32.store offset=8
70+
i32.const 1168
71+
i32.load
72+
call_indirect (type $0)
73+
global.get $~lib/memory/__stack_pointer
74+
i32.const 12
75+
i32.add
76+
global.set $~lib/memory/__stack_pointer
77+
)
78+
(func $~lib/string/String.__eq (param $0 i32) (param $1 i32) (result i32)
79+
(local $2 i32)
80+
(local $3 i32)
81+
(local $4 i32)
82+
(local $5 i32)
83+
global.get $~lib/memory/__stack_pointer
84+
i32.const 8
85+
i32.sub
86+
global.set $~lib/memory/__stack_pointer
87+
global.get $~lib/memory/__stack_pointer
88+
i32.const 1180
89+
i32.lt_s
90+
if
91+
i32.const 33968
92+
i32.const 34016
93+
i32.const 1
94+
i32.const 1
95+
call $~lib/builtins/abort
96+
unreachable
97+
end
98+
global.get $~lib/memory/__stack_pointer
99+
local.tee $2
100+
i64.const 0
101+
i64.store
102+
local.get $0
103+
local.get $1
104+
i32.eq
105+
if
106+
local.get $2
107+
i32.const 8
108+
i32.add
109+
global.set $~lib/memory/__stack_pointer
110+
i32.const 1
111+
return
112+
end
113+
block $folding-inner0
114+
local.get $1
115+
i32.eqz
116+
local.get $0
117+
i32.eqz
118+
i32.or
119+
br_if $folding-inner0
120+
global.get $~lib/memory/__stack_pointer
121+
local.tee $4
122+
local.tee $2
123+
local.get $0
124+
i32.store
125+
local.get $0
126+
i32.const 20
127+
i32.sub
128+
i32.load offset=16
129+
i32.const 1
130+
i32.shr_u
131+
local.set $3
132+
local.get $2
133+
local.get $1
134+
i32.store
135+
local.get $3
136+
local.get $1
137+
i32.const 20
138+
i32.sub
139+
i32.load offset=16
140+
i32.const 1
141+
i32.shr_u
142+
i32.ne
143+
br_if $folding-inner0
144+
local.get $4
145+
local.get $0
146+
i32.store
147+
local.get $0
148+
local.set $2
149+
local.get $4
150+
local.get $1
151+
i32.store offset=4
152+
local.get $3
153+
local.tee $0
154+
i32.const 4
155+
i32.ge_u
156+
if (result i32)
157+
local.get $2
158+
i32.const 7
159+
i32.and
160+
local.get $1
161+
i32.const 7
162+
i32.and
163+
i32.or
164+
else
165+
i32.const 1
166+
end
167+
i32.eqz
168+
if
169+
loop $do-loop|0
170+
local.get $2
171+
i64.load
172+
local.get $1
173+
i64.load
174+
i64.eq
175+
if
176+
local.get $2
177+
i32.const 8
178+
i32.add
179+
local.set $2
180+
local.get $1
181+
i32.const 8
182+
i32.add
183+
local.set $1
184+
local.get $0
185+
i32.const 4
186+
i32.sub
187+
local.tee $0
188+
i32.const 4
189+
i32.ge_u
190+
br_if $do-loop|0
191+
end
192+
end
193+
end
194+
block $__inlined_func$~lib/util/string/compareImpl$5
195+
loop $while-continue|1
196+
local.get $0
197+
local.tee $3
198+
i32.const 1
199+
i32.sub
200+
local.set $0
201+
local.get $3
202+
if
203+
local.get $2
204+
i32.load16_u
205+
local.tee $5
206+
local.get $1
207+
i32.load16_u
208+
local.tee $4
209+
i32.sub
210+
local.set $3
211+
local.get $4
212+
local.get $5
213+
i32.ne
214+
br_if $__inlined_func$~lib/util/string/compareImpl$5
215+
local.get $2
216+
i32.const 2
217+
i32.add
218+
local.set $2
219+
local.get $1
220+
i32.const 2
221+
i32.add
222+
local.set $1
223+
br $while-continue|1
224+
end
225+
end
226+
i32.const 0
227+
local.set $3
228+
end
229+
global.get $~lib/memory/__stack_pointer
230+
i32.const 8
231+
i32.add
232+
global.set $~lib/memory/__stack_pointer
233+
local.get $3
234+
i32.eqz
235+
return
236+
end
237+
global.get $~lib/memory/__stack_pointer
238+
i32.const 8
239+
i32.add
240+
global.set $~lib/memory/__stack_pointer
241+
i32.const 0
242+
)
243+
(func $typealias/outer_function~inner_function
244+
(local $0 i32)
245+
global.get $~lib/memory/__stack_pointer
246+
i32.const 8
247+
i32.sub
248+
global.set $~lib/memory/__stack_pointer
249+
global.get $~lib/memory/__stack_pointer
250+
i32.const 1180
251+
i32.lt_s
252+
if
253+
i32.const 33968
254+
i32.const 34016
255+
i32.const 1
256+
i32.const 1
257+
call $~lib/builtins/abort
258+
unreachable
259+
end
260+
global.get $~lib/memory/__stack_pointer
261+
local.tee $0
262+
i64.const 0
263+
i64.store
264+
local.get $0
265+
i32.const 1136
266+
i32.store
267+
local.get $0
268+
i32.const 1136
269+
i32.store offset=4
270+
i32.const 1136
271+
i32.const 1136
272+
call $~lib/string/String.__eq
273+
i32.eqz
274+
if
275+
i32.const 0
276+
i32.const 1088
277+
i32.const 17
278+
i32.const 5
279+
call $~lib/builtins/abort
280+
unreachable
281+
end
282+
global.get $~lib/memory/__stack_pointer
283+
i32.const 8
284+
i32.add
285+
global.set $~lib/memory/__stack_pointer
286+
)
9287
)

‎tests/compiler/typealias.ts

+26
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,29 @@ export type alias = i32;
66
export function alias(a: alias): alias {
77
return a;
88
}
9+
10+
function outer_function(): void {
11+
type alias = i64;
12+
let alias: alias = 1;
13+
assert(nameof(alias) == nameof<i64>());
14+
function inner_function(): void {
15+
type alias = f64;
16+
let alias: alias = 1;
17+
assert(nameof(alias) == nameof<f64>());
18+
}
19+
inner_function();
20+
}
21+
outer_function();
22+
23+
function generic_type_alias(): void {
24+
type V<T> = Array<T>;
25+
assert(idof<V<i32>>() == idof<Array<i32>>());
26+
}
27+
generic_type_alias();
28+
29+
30+
function alias_in_type_arguments(): void {
31+
type alias = i64;
32+
assert(idof<Array<alias>>() == idof<Array<i64>>());
33+
}
34+
alias_in_type_arguments();

0 commit comments

Comments
 (0)
Please sign in to comment.