TypeScript 3.1.5 corrects emitted aliases for const enums
TypeScript 3.1.5 aligns two compiler decisions about whether an alias refers to a runtime value. The correction prevents an exported const-enum alias from acquiring unnecessary JavaScript output.
An exported name in a TypeScript declaration does not always require an exported value in JavaScript. Const-enum uses can become literal values during compilation, leaving no runtime enum object for an alias to reference. TypeScript 3.1.5 corrects a disagreement inside the compiler about when such an alias needs emitted code.
The npm registry records publication on October 31. Its patch from 3.1.4 to 3.1.5 changes the condition used by isReferencedAliasDeclaration(), aligning it with the value-resolution condition. The associated regression test shows an exported import alias for a const enum and the JavaScript that should remain after compilation.
I am cautious about TypeScript features that introduce extra distinctions between source and runtime, while valuing its ability to describe existing JavaScript interfaces. This maintenance change concerns exactly that boundary. A checked declaration can remain meaningful to consumers without requiring a corresponding runtime assignment in the generated program.
Const-enum uses can become literals
The regression fixture declares const enums inside a namespace-style module. Another part of the namespace exports an import-equals alias for one enum and uses a member through that alias. It also creates an unexported alias for another enum, providing a comparison case.
The JavaScript baseline at the release tag replaces the selected enum members with their numeric constants. A member selected through the exported alias becomes a numeric literal, just as a member accessed through the unexported alias does.
An illustrative source arrangement uses the same alias form.
namespace Model {
export const enum Result {
Pending,
Ready
}
}
namespace PublicModel {
export import Result = Model.Result;
export function readyCode(): number {
return Result.Ready;
}
}
The import-equals declaration here is a namespace alias, not an ECMAScript module import statement. Its exported status makes the name available through the declaration structure. That alone should not force the compiler to materialize a JavaScript alias when the const-enum reference is substituted and enum preservation is disabled.
This distinction is central to understanding the bug. The source has an exported name, but the generated program's relevant operation is returning a constant. Emitting another assignment requires a reason grounded in the runtime representation, not merely the presence of the export modifier.
The original fixture also exports an ordinary function from the namespace containing the enum. Its JavaScript remains in the baseline, so the test does not depend on erasing the entire surrounding namespace. It isolates the enum-alias decision within a structure that still has a legitimate runtime value. That makes the expected omission more specific than removing every declaration in an otherwise empty container.
Two compiler predicates must agree
Before the correction, the alias-reference check treated an exported alias targeting a value symbol as always referenced. The patch adds a condition for const enums and modules containing only const enums. Such targets qualify under this branch only when preserveConstEnums requests their preservation, or when the target is not in that special erased category.
That condition connects the reference decision to the emission policy. A symbol carrying value-related flags is not sufficient evidence that its ordinary runtime representation should survive in every compilation mode. The compiler must also account for a construct whose uses can be substituted.
The change is small, but it repairs agreement between two internal questions. One asks whether an alias resolves to a value under the relevant conditions. Another asks whether it is referenced strongly enough to require output. If those answers use incompatible criteria, the emitter can retain a declaration for something another part of compilation expects to disappear.
This is an implementation explanation, not a claim that all exported aliases are erased. The new condition explicitly preserves the distinction for ordinary runtime values and for the option requesting const-enum preservation. The correction concerns a specific category of target under a specific emission policy.
Declaration output retains the public type relationship
The regression fixture also enables declaration generation. Its expected .d.ts output retains the exported alias for the const enum. The JavaScript output omits the corresponding unnecessary alias while the declaration continues to describe the public name.
Those outputs have different purposes. A declaration consumer needs the relationship among exported names and types. The JavaScript runtime needs the executable operations left after substitution. A successful fix must preserve both requirements, rather than deleting the alias indiscriminately from every output artifact.
The fixture includes an interface alias as another comparison. That relationship also belongs in declarations without creating an executable value merely because the alias is exported. These examples make the intended split between declaration information and runtime output observable in the checked-in baselines.
My judgement is that this patch is best understood through those output differences. It aligns the compiler's reference decision with its const-enum emission policy, while preserving the declaration-level name for consumers. The maintenance release changes no application call syntax, but it corrects what the compiler decides must exist in the resulting JavaScript.