--erasableSyntaxOnly (#61011)

Co-authored-by: Jake Bailey <5341706+jakebailey@users.noreply.github.com>
This commit is contained in:
Ryan Cavanaugh 2025-01-23 15:56:35 -08:00 committed by GitHub
parent 329387d76f
commit 2c865e461e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 832 additions and 3 deletions

View File

@ -41295,6 +41295,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
checkVariableLikeDeclaration(node);
const func = getContainingFunction(node)!;
if (hasSyntacticModifier(node, ModifierFlags.ParameterPropertyModifier)) {
if (compilerOptions.erasableSyntaxOnly) {
error(node, Diagnostics.This_syntax_is_not_allowed_when_erasableSyntaxOnly_is_enabled);
}
if (!(func.kind === SyntaxKind.Constructor && nodeIsPresent(func.body))) {
error(node, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
}
@ -47509,6 +47512,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
checkExportsOnMergedDeclarations(node);
node.members.forEach(checkEnumMember);
if (compilerOptions.erasableSyntaxOnly && !(node.flags & NodeFlags.Ambient)) {
error(node, Diagnostics.This_syntax_is_not_allowed_when_erasableSyntaxOnly_is_enabled);
}
computeEnumMemberValues(node);
// Spec 2014 - Section 9.3:
@ -47648,6 +47655,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
&& !inAmbientContext
&& isInstantiatedModule(node, shouldPreserveConstEnums(compilerOptions))
) {
if (compilerOptions.erasableSyntaxOnly) {
error(node.name, Diagnostics.This_syntax_is_not_allowed_when_erasableSyntaxOnly_is_enabled);
}
if (getIsolatedModules(compilerOptions) && !getSourceFileOfNode(node).externalModuleIndicator) {
// This could be loosened a little if needed. The only problem we are trying to avoid is unqualified
// references to namespace members declared in other files. But use of namespaces is discouraged anyway,
@ -48164,7 +48175,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
checkGrammarModifiers(node);
if (isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) {
const isImportEquals = isInternalModuleImportEqualsDeclaration(node);
if (compilerOptions.erasableSyntaxOnly && isImportEquals && !(node.flags & NodeFlags.Ambient)) {
error(node, Diagnostics.This_syntax_is_not_allowed_when_erasableSyntaxOnly_is_enabled);
}
if (isImportEquals || checkExternalImportOrExportDeclaration(node)) {
checkImportBinding(node);
markLinkedReferences(node, ReferenceHint.ExportImportEquals);
if (node.moduleReference.kind !== SyntaxKind.ExternalModuleReference) {

View File

@ -856,6 +856,15 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [
affectsBuildInfo: true,
affectsSemanticDiagnostics: true,
},
{
name: "erasableSyntaxOnly",
type: "boolean",
category: Diagnostics.Interop_Constraints,
description: Diagnostics.Do_not_allow_runtime_constructs_that_are_not_part_of_ECMAScript,
defaultValueDescription: false,
affectsBuildInfo: true,
affectsSemanticDiagnostics: true,
},
// Strict Type Checks
{

View File

@ -971,7 +971,10 @@
"category": "Error",
"code": 1293
},
"This syntax is not allowed when 'erasableSyntaxOnly' is enabled.": {
"category": "Error",
"code": 1294
},
"'with' statements are not allowed in an async function block.": {
"category": "Error",
"code": 1300
@ -6471,11 +6474,14 @@
"category": "Message",
"code": 6719
},
"Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'.": {
"category": "Message",
"code": 6720
},
"Do not allow runtime constructs that are not part of ECMAScript.": {
"category": "Message",
"code": 6721
},
"Default catch clause variables as 'unknown' instead of 'any'.": {
"category": "Message",
"code": 6803

View File

@ -7502,6 +7502,7 @@ export interface CompilerOptions {
/** Paths used to compute primary types search locations */
typeRoots?: string[];
verbatimModuleSyntax?: boolean;
erasableSyntaxOnly?: boolean;
/** @internal */ version?: boolean;
/** @internal */ watch?: boolean;
esModuleInterop?: boolean;

View File

@ -7102,6 +7102,7 @@ declare namespace ts {
/** Paths used to compute primary types search locations */
typeRoots?: string[];
verbatimModuleSyntax?: boolean;
erasableSyntaxOnly?: boolean;
esModuleInterop?: boolean;
useDefineForClassFields?: boolean;
[option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined;

View File

@ -77,6 +77,7 @@
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
// "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */

View File

@ -77,6 +77,7 @@
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
// "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */

View File

@ -77,6 +77,7 @@
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
// "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */

View File

@ -77,6 +77,7 @@
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
// "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */

View File

@ -77,6 +77,7 @@
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
// "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */

View File

@ -77,6 +77,7 @@
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
// "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */

View File

@ -77,6 +77,7 @@
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
// "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */

View File

@ -77,6 +77,7 @@
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
// "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */

View File

@ -77,6 +77,7 @@
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
// "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */

View File

@ -77,6 +77,7 @@
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
// "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */

View File

@ -77,6 +77,7 @@
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
// "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */

View File

@ -0,0 +1,5 @@
{
"compilerOptions": {
"erasableSyntaxOnly": true
}
}

View File

@ -0,0 +1,92 @@
erasableSyntaxOnly.ts(3,17): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
erasableSyntaxOnly.ts(6,11): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
erasableSyntaxOnly.ts(10,11): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
erasableSyntaxOnly.ts(16,11): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
erasableSyntaxOnly.ts(17,15): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
erasableSyntaxOnly.ts(22,6): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
erasableSyntaxOnly.ts(26,1): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
erasableSyntaxOnly.ts(28,12): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
==== erasableSyntaxOnly.ts (8 errors) ====
class MyClassErr {
// No parameter properties
constructor(public foo: string) { }
~~~~~~~~~~~~~~~~~~
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
}
namespace IllegalBecauseInstantiated {
~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
export const m = 1;
}
namespace AlsoIllegalBecauseInstantiated {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
class PrivateClass {
}
}
namespace IllegalBecauseNestedInstantiated {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
namespace Nested {
~~~~~~
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
export const m = 1;
}
}
enum NotLegalEnum {
~~~~~~~~~~~~
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
B = 1
}
import NoGoodAlias = NotLegalEnum.B;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
const enum NotLegalConstEnum {
~~~~~~~~~~~~~~~~~
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
C = 2
}
// No errors after this point
class MyClassOk {
// Not a parameter property, ok
constructor(foo: string) { }
}
// Note for implementors: This should not be an error
// as this entire namespace block is fully erased
namespace NotInstantiated {
export interface JustAType { }
export type ATypeInANamespace = {};
namespace Nested {
export type ATypeInANamespace = {};
}
}
declare namespace AmbientIsNotInstantiated {
export const stillOk = 12;
}
declare enum LegalEnum {
A = 1
}
declare namespace AmbientStuff {
namespace Nested {
export const stillOk = 12;
}
enum EnumInAmbientContext {
B = 1
}
import FineAlias = EnumInAmbientContext.B;
}

View File

@ -0,0 +1,120 @@
//// [tests/cases/compiler/erasableSyntaxOnly.ts] ////
=== erasableSyntaxOnly.ts ===
class MyClassErr {
>MyClassErr : Symbol(MyClassErr, Decl(erasableSyntaxOnly.ts, 0, 0))
// No parameter properties
constructor(public foo: string) { }
>foo : Symbol(MyClassErr.foo, Decl(erasableSyntaxOnly.ts, 2, 16))
}
namespace IllegalBecauseInstantiated {
>IllegalBecauseInstantiated : Symbol(IllegalBecauseInstantiated, Decl(erasableSyntaxOnly.ts, 3, 1))
export const m = 1;
>m : Symbol(m, Decl(erasableSyntaxOnly.ts, 6, 16))
}
namespace AlsoIllegalBecauseInstantiated {
>AlsoIllegalBecauseInstantiated : Symbol(AlsoIllegalBecauseInstantiated, Decl(erasableSyntaxOnly.ts, 7, 1))
class PrivateClass {
>PrivateClass : Symbol(PrivateClass, Decl(erasableSyntaxOnly.ts, 9, 42))
}
}
namespace IllegalBecauseNestedInstantiated {
>IllegalBecauseNestedInstantiated : Symbol(IllegalBecauseNestedInstantiated, Decl(erasableSyntaxOnly.ts, 13, 1))
namespace Nested {
>Nested : Symbol(Nested, Decl(erasableSyntaxOnly.ts, 15, 44))
export const m = 1;
>m : Symbol(m, Decl(erasableSyntaxOnly.ts, 17, 20))
}
}
enum NotLegalEnum {
>NotLegalEnum : Symbol(NotLegalEnum, Decl(erasableSyntaxOnly.ts, 19, 1))
B = 1
>B : Symbol(NoGoodAlias, Decl(erasableSyntaxOnly.ts, 21, 19))
}
import NoGoodAlias = NotLegalEnum.B;
>NoGoodAlias : Symbol(NoGoodAlias, Decl(erasableSyntaxOnly.ts, 23, 1))
>NotLegalEnum : Symbol(NotLegalEnum, Decl(erasableSyntaxOnly.ts, 19, 1))
>B : Symbol(NoGoodAlias, Decl(erasableSyntaxOnly.ts, 21, 19))
const enum NotLegalConstEnum {
>NotLegalConstEnum : Symbol(NotLegalConstEnum, Decl(erasableSyntaxOnly.ts, 25, 36))
C = 2
>C : Symbol(NotLegalConstEnum.C, Decl(erasableSyntaxOnly.ts, 27, 30))
}
// No errors after this point
class MyClassOk {
>MyClassOk : Symbol(MyClassOk, Decl(erasableSyntaxOnly.ts, 29, 1))
// Not a parameter property, ok
constructor(foo: string) { }
>foo : Symbol(foo, Decl(erasableSyntaxOnly.ts, 34, 16))
}
// Note for implementors: This should not be an error
// as this entire namespace block is fully erased
namespace NotInstantiated {
>NotInstantiated : Symbol(NotInstantiated, Decl(erasableSyntaxOnly.ts, 35, 1))
export interface JustAType { }
>JustAType : Symbol(JustAType, Decl(erasableSyntaxOnly.ts, 39, 27))
export type ATypeInANamespace = {};
>ATypeInANamespace : Symbol(ATypeInANamespace, Decl(erasableSyntaxOnly.ts, 40, 34))
namespace Nested {
>Nested : Symbol(Nested, Decl(erasableSyntaxOnly.ts, 41, 39))
export type ATypeInANamespace = {};
>ATypeInANamespace : Symbol(ATypeInANamespace, Decl(erasableSyntaxOnly.ts, 42, 22))
}
}
declare namespace AmbientIsNotInstantiated {
>AmbientIsNotInstantiated : Symbol(AmbientIsNotInstantiated, Decl(erasableSyntaxOnly.ts, 45, 1))
export const stillOk = 12;
>stillOk : Symbol(stillOk, Decl(erasableSyntaxOnly.ts, 47, 16))
}
declare enum LegalEnum {
>LegalEnum : Symbol(LegalEnum, Decl(erasableSyntaxOnly.ts, 48, 1))
A = 1
>A : Symbol(LegalEnum.A, Decl(erasableSyntaxOnly.ts, 50, 24))
}
declare namespace AmbientStuff {
>AmbientStuff : Symbol(AmbientStuff, Decl(erasableSyntaxOnly.ts, 52, 1))
namespace Nested {
>Nested : Symbol(Nested, Decl(erasableSyntaxOnly.ts, 54, 32))
export const stillOk = 12;
>stillOk : Symbol(stillOk, Decl(erasableSyntaxOnly.ts, 56, 20))
}
enum EnumInAmbientContext {
>EnumInAmbientContext : Symbol(EnumInAmbientContext, Decl(erasableSyntaxOnly.ts, 57, 5))
B = 1
>B : Symbol(FineAlias, Decl(erasableSyntaxOnly.ts, 58, 31))
}
import FineAlias = EnumInAmbientContext.B;
>FineAlias : Symbol(FineAlias, Decl(erasableSyntaxOnly.ts, 60, 5))
>EnumInAmbientContext : Symbol(EnumInAmbientContext, Decl(erasableSyntaxOnly.ts, 57, 5))
>B : Symbol(FineAlias, Decl(erasableSyntaxOnly.ts, 58, 31))
}

View File

@ -0,0 +1,162 @@
//// [tests/cases/compiler/erasableSyntaxOnly.ts] ////
=== erasableSyntaxOnly.ts ===
class MyClassErr {
>MyClassErr : MyClassErr
> : ^^^^^^^^^^
// No parameter properties
constructor(public foo: string) { }
>foo : string
> : ^^^^^^
}
namespace IllegalBecauseInstantiated {
>IllegalBecauseInstantiated : typeof IllegalBecauseInstantiated
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
export const m = 1;
>m : 1
> : ^
>1 : 1
> : ^
}
namespace AlsoIllegalBecauseInstantiated {
>AlsoIllegalBecauseInstantiated : typeof AlsoIllegalBecauseInstantiated
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
class PrivateClass {
>PrivateClass : PrivateClass
> : ^^^^^^^^^^^^
}
}
namespace IllegalBecauseNestedInstantiated {
>IllegalBecauseNestedInstantiated : typeof IllegalBecauseNestedInstantiated
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
namespace Nested {
>Nested : typeof Nested
> : ^^^^^^^^^^^^^
export const m = 1;
>m : 1
> : ^
>1 : 1
> : ^
}
}
enum NotLegalEnum {
>NotLegalEnum : NotLegalEnum
> : ^^^^^^^^^^^^
B = 1
>B : NotLegalEnum.B
> : ^^^^^^^^^^^^^^
>1 : 1
> : ^
}
import NoGoodAlias = NotLegalEnum.B;
>NoGoodAlias : NotLegalEnum.B
> : ^^^^^^^^^^^^^^
>NotLegalEnum : NotLegalEnum
> : ^^^^^^^^^^^^
>B : NotLegalEnum.B
> : ^^^^^^^^^^^^^^
const enum NotLegalConstEnum {
>NotLegalConstEnum : NotLegalConstEnum
> : ^^^^^^^^^^^^^^^^^
C = 2
>C : NotLegalConstEnum.C
> : ^^^^^^^^^^^^^^^^^^^
>2 : 2
> : ^
}
// No errors after this point
class MyClassOk {
>MyClassOk : MyClassOk
> : ^^^^^^^^^
// Not a parameter property, ok
constructor(foo: string) { }
>foo : string
> : ^^^^^^
}
// Note for implementors: This should not be an error
// as this entire namespace block is fully erased
namespace NotInstantiated {
export interface JustAType { }
export type ATypeInANamespace = {};
>ATypeInANamespace : ATypeInANamespace
> : ^^^^^^^^^^^^^^^^^
namespace Nested {
export type ATypeInANamespace = {};
>ATypeInANamespace : ATypeInANamespace
> : ^^^^^^^^^^^^^^^^^
}
}
declare namespace AmbientIsNotInstantiated {
>AmbientIsNotInstantiated : typeof AmbientIsNotInstantiated
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
export const stillOk = 12;
>stillOk : 12
> : ^^
>12 : 12
> : ^^
}
declare enum LegalEnum {
>LegalEnum : LegalEnum
> : ^^^^^^^^^
A = 1
>A : LegalEnum.A
> : ^^^^^^^^^^^
>1 : 1
> : ^
}
declare namespace AmbientStuff {
>AmbientStuff : typeof AmbientStuff
> : ^^^^^^^^^^^^^^^^^^^
namespace Nested {
>Nested : typeof Nested
> : ^^^^^^^^^^^^^
export const stillOk = 12;
>stillOk : 12
> : ^^
>12 : 12
> : ^^
}
enum EnumInAmbientContext {
>EnumInAmbientContext : EnumInAmbientContext
> : ^^^^^^^^^^^^^^^^^^^^
B = 1
>B : EnumInAmbientContext.B
> : ^^^^^^^^^^^^^^^^^^^^^^
>1 : 1
> : ^
}
import FineAlias = EnumInAmbientContext.B;
>FineAlias : EnumInAmbientContext.B
> : ^^^^^^^^^^^^^^^^^^^^^^
>EnumInAmbientContext : EnumInAmbientContext
> : ^^^^^^^^^^^^^^^^^^^^
>B : EnumInAmbientContext.B
> : ^^^^^^^^^^^^^^^^^^^^^^
}

View File

@ -0,0 +1,57 @@
decl.d.ts(4,1): error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier.
==== decl.d.ts (1 errors) ====
// Diffs from the other test:
// - Parameter properties are already banned in .d.ts files
namespace IllegalBecauseInstantiated {
~~~~~~~~~
!!! error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier.
export const m = 1;
}
namespace AlsoIllegalBecauseInstantiated {
class PrivateClass {
}
}
enum NotLegalEnum {
B = 1
}
import NoGoodAlias = NotLegalEnum.B;
const enum NotLegalConstEnum {
C = 2
}
// No errors after this point
class MyClassOk {
// Not a parameter property, ok
constructor(foo: string);
}
namespace NotInstantiated {
export interface JustAType { }
export type ATypeInANamespace = {};
}
declare namespace AmbientIsNotInstantiated {
export const stillOk = 12;
}
declare enum LegalEnum {
A = 1
}
declare namespace AmbientStuff {
namespace Nested {
export const stillOk = 12;
}
enum EnumInAmbientContext {
B = 1
}
import FineAlias = EnumInAmbientContext.B;
}

View File

@ -0,0 +1,94 @@
//// [tests/cases/compiler/erasableSyntaxOnlyDeclaration.ts] ////
=== decl.d.ts ===
// Diffs from the other test:
// - Parameter properties are already banned in .d.ts files
namespace IllegalBecauseInstantiated {
>IllegalBecauseInstantiated : Symbol(IllegalBecauseInstantiated, Decl(decl.d.ts, 0, 0))
export const m = 1;
>m : Symbol(m, Decl(decl.d.ts, 4, 16))
}
namespace AlsoIllegalBecauseInstantiated {
>AlsoIllegalBecauseInstantiated : Symbol(AlsoIllegalBecauseInstantiated, Decl(decl.d.ts, 5, 1))
class PrivateClass {
>PrivateClass : Symbol(PrivateClass, Decl(decl.d.ts, 7, 42))
}
}
enum NotLegalEnum {
>NotLegalEnum : Symbol(NotLegalEnum, Decl(decl.d.ts, 11, 1))
B = 1
>B : Symbol(NoGoodAlias, Decl(decl.d.ts, 13, 19))
}
import NoGoodAlias = NotLegalEnum.B;
>NoGoodAlias : Symbol(NoGoodAlias, Decl(decl.d.ts, 15, 1))
>NotLegalEnum : Symbol(NotLegalEnum, Decl(decl.d.ts, 11, 1))
>B : Symbol(NoGoodAlias, Decl(decl.d.ts, 13, 19))
const enum NotLegalConstEnum {
>NotLegalConstEnum : Symbol(NotLegalConstEnum, Decl(decl.d.ts, 17, 36))
C = 2
>C : Symbol(NotLegalConstEnum.C, Decl(decl.d.ts, 19, 30))
}
// No errors after this point
class MyClassOk {
>MyClassOk : Symbol(MyClassOk, Decl(decl.d.ts, 21, 1))
// Not a parameter property, ok
constructor(foo: string);
>foo : Symbol(foo, Decl(decl.d.ts, 26, 16))
}
namespace NotInstantiated {
>NotInstantiated : Symbol(NotInstantiated, Decl(decl.d.ts, 27, 1))
export interface JustAType { }
>JustAType : Symbol(JustAType, Decl(decl.d.ts, 28, 27))
export type ATypeInANamespace = {};
>ATypeInANamespace : Symbol(ATypeInANamespace, Decl(decl.d.ts, 29, 34))
}
declare namespace AmbientIsNotInstantiated {
>AmbientIsNotInstantiated : Symbol(AmbientIsNotInstantiated, Decl(decl.d.ts, 31, 1))
export const stillOk = 12;
>stillOk : Symbol(stillOk, Decl(decl.d.ts, 33, 16))
}
declare enum LegalEnum {
>LegalEnum : Symbol(LegalEnum, Decl(decl.d.ts, 34, 1))
A = 1
>A : Symbol(LegalEnum.A, Decl(decl.d.ts, 36, 24))
}
declare namespace AmbientStuff {
>AmbientStuff : Symbol(AmbientStuff, Decl(decl.d.ts, 38, 1))
namespace Nested {
>Nested : Symbol(Nested, Decl(decl.d.ts, 40, 32))
export const stillOk = 12;
>stillOk : Symbol(stillOk, Decl(decl.d.ts, 42, 20))
}
enum EnumInAmbientContext {
>EnumInAmbientContext : Symbol(EnumInAmbientContext, Decl(decl.d.ts, 43, 5))
B = 1
>B : Symbol(FineAlias, Decl(decl.d.ts, 44, 31))
}
import FineAlias = EnumInAmbientContext.B;
>FineAlias : Symbol(FineAlias, Decl(decl.d.ts, 46, 5))
>EnumInAmbientContext : Symbol(EnumInAmbientContext, Decl(decl.d.ts, 43, 5))
>B : Symbol(FineAlias, Decl(decl.d.ts, 44, 31))
}

View File

@ -0,0 +1,130 @@
//// [tests/cases/compiler/erasableSyntaxOnlyDeclaration.ts] ////
=== decl.d.ts ===
// Diffs from the other test:
// - Parameter properties are already banned in .d.ts files
namespace IllegalBecauseInstantiated {
>IllegalBecauseInstantiated : typeof IllegalBecauseInstantiated
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
export const m = 1;
>m : 1
> : ^
>1 : 1
> : ^
}
namespace AlsoIllegalBecauseInstantiated {
>AlsoIllegalBecauseInstantiated : typeof AlsoIllegalBecauseInstantiated
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
class PrivateClass {
>PrivateClass : PrivateClass
> : ^^^^^^^^^^^^
}
}
enum NotLegalEnum {
>NotLegalEnum : NotLegalEnum
> : ^^^^^^^^^^^^
B = 1
>B : NotLegalEnum.B
> : ^^^^^^^^^^^^^^
>1 : 1
> : ^
}
import NoGoodAlias = NotLegalEnum.B;
>NoGoodAlias : NotLegalEnum.B
> : ^^^^^^^^^^^^^^
>NotLegalEnum : NotLegalEnum
> : ^^^^^^^^^^^^
>B : NotLegalEnum.B
> : ^^^^^^^^^^^^^^
const enum NotLegalConstEnum {
>NotLegalConstEnum : NotLegalConstEnum
> : ^^^^^^^^^^^^^^^^^
C = 2
>C : NotLegalConstEnum.C
> : ^^^^^^^^^^^^^^^^^^^
>2 : 2
> : ^
}
// No errors after this point
class MyClassOk {
>MyClassOk : MyClassOk
> : ^^^^^^^^^
// Not a parameter property, ok
constructor(foo: string);
>foo : string
> : ^^^^^^
}
namespace NotInstantiated {
export interface JustAType { }
export type ATypeInANamespace = {};
>ATypeInANamespace : ATypeInANamespace
> : ^^^^^^^^^^^^^^^^^
}
declare namespace AmbientIsNotInstantiated {
>AmbientIsNotInstantiated : typeof AmbientIsNotInstantiated
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
export const stillOk = 12;
>stillOk : 12
> : ^^
>12 : 12
> : ^^
}
declare enum LegalEnum {
>LegalEnum : LegalEnum
> : ^^^^^^^^^
A = 1
>A : LegalEnum.A
> : ^^^^^^^^^^^
>1 : 1
> : ^
}
declare namespace AmbientStuff {
>AmbientStuff : typeof AmbientStuff
> : ^^^^^^^^^^^^^^^^^^^
namespace Nested {
>Nested : typeof Nested
> : ^^^^^^^^^^^^^
export const stillOk = 12;
>stillOk : 12
> : ^^
>12 : 12
> : ^^
}
enum EnumInAmbientContext {
>EnumInAmbientContext : EnumInAmbientContext
> : ^^^^^^^^^^^^^^^^^^^^
B = 1
>B : EnumInAmbientContext.B
> : ^^^^^^^^^^^^^^^^^^^^^^
>1 : 1
> : ^
}
import FineAlias = EnumInAmbientContext.B;
>FineAlias : EnumInAmbientContext.B
> : ^^^^^^^^^^^^^^^^^^^^^^
>EnumInAmbientContext : EnumInAmbientContext
> : ^^^^^^^^^^^^^^^^^^^^
>B : EnumInAmbientContext.B
> : ^^^^^^^^^^^^^^^^^^^^^^
}

View File

@ -167,6 +167,11 @@ Allow 'import x from y' when a module doesn't have a default export.
type: boolean
default: module === "system" or esModuleInterop
--erasableSyntaxOnly
Do not allow runtime constructs that are not part of ECMAScript.
type: boolean
default: false
--esModuleInterop
Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility.
type: boolean

View File

@ -0,0 +1,67 @@
// @erasableSyntaxOnly: true
// @noEmit: true
class MyClassErr {
// No parameter properties
constructor(public foo: string) { }
}
namespace IllegalBecauseInstantiated {
export const m = 1;
}
namespace AlsoIllegalBecauseInstantiated {
class PrivateClass {
}
}
namespace IllegalBecauseNestedInstantiated {
namespace Nested {
export const m = 1;
}
}
enum NotLegalEnum {
B = 1
}
import NoGoodAlias = NotLegalEnum.B;
const enum NotLegalConstEnum {
C = 2
}
// No errors after this point
class MyClassOk {
// Not a parameter property, ok
constructor(foo: string) { }
}
// Note for implementors: This should not be an error
// as this entire namespace block is fully erased
namespace NotInstantiated {
export interface JustAType { }
export type ATypeInANamespace = {};
namespace Nested {
export type ATypeInANamespace = {};
}
}
declare namespace AmbientIsNotInstantiated {
export const stillOk = 12;
}
declare enum LegalEnum {
A = 1
}
declare namespace AmbientStuff {
namespace Nested {
export const stillOk = 12;
}
enum EnumInAmbientContext {
B = 1
}
import FineAlias = EnumInAmbientContext.B;
}

View File

@ -0,0 +1,54 @@
// @erasableSyntaxOnly: true
// @noEmit: true
// @filename: decl.d.ts
// Diffs from the other test:
// - Parameter properties are already banned in .d.ts files
namespace IllegalBecauseInstantiated {
export const m = 1;
}
namespace AlsoIllegalBecauseInstantiated {
class PrivateClass {
}
}
enum NotLegalEnum {
B = 1
}
import NoGoodAlias = NotLegalEnum.B;
const enum NotLegalConstEnum {
C = 2
}
// No errors after this point
class MyClassOk {
// Not a parameter property, ok
constructor(foo: string);
}
namespace NotInstantiated {
export interface JustAType { }
export type ATypeInANamespace = {};
}
declare namespace AmbientIsNotInstantiated {
export const stillOk = 12;
}
declare enum LegalEnum {
A = 1
}
declare namespace AmbientStuff {
namespace Nested {
export const stillOk = 12;
}
enum EnumInAmbientContext {
B = 1
}
import FineAlias = EnumInAmbientContext.B;
}