Update type-only import semantics to allow type queries (#36092)

* Change type-only semantics to allow type queries

* Don’t error using type-only import in ambient context

* Fix default import

* Fix namespace import

* Update more baselines

* Prevent circular resolution

* Track const enum expression usage

* Update baselines

* Perf tuning 1

* Test commit for perf impact

* Weave type-only alias declaration finding into alias resolution

* Fix namespace import of type-only exported symbols

* type-only exports do not contribute to the module object type

* Update APIs

* Fix enum casing, remove type-only conversion suggestion

* Short circuit type-only checks in resolveEntityName faster

* Fix casing in API

* Remove unused parameter

* Fix error on qualified names in type queries

* Allow type-only imports in computed property names

* Fix computed property names of types and abstract members

* Remove unused util

* Commit missing baselines

* Rename “check” functions so as not to overload the word “check”
This commit is contained in:
Andrew Branch
2020-01-23 12:53:36 -08:00
committed by GitHub
parent 0276e7f910
commit b05dde747c
76 changed files with 1406 additions and 326 deletions
+131 -156
View File
@@ -1861,10 +1861,36 @@ namespace ts {
error(errorLocation, Diagnostics.Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it, declarationNameToString(associatedDeclarationForContainingInitializer.name), declarationNameToString(<Identifier>errorLocation));
}
}
if (result && errorLocation && meaning & SymbolFlags.Value && result.flags & SymbolFlags.Alias) {
checkSymbolUsageInExpressionContext(result, name, errorLocation);
}
}
return result;
}
function checkSymbolUsageInExpressionContext(symbol: Symbol, name: __String, useSite: Node) {
if (
!(useSite.flags & NodeFlags.Ambient) &&
!isPartOfTypeQuery(useSite) &&
!isPartOfPossiblyValidTypeOrAbstractComputedPropertyName(useSite) &&
isExpressionNode(useSite)
) {
const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(symbol);
if (typeOnlyDeclaration) {
const message = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier
? Diagnostics._0_cannot_be_used_as_a_value_because_it_was_exported_using_export_type
: Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type;
const relatedMessage = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier
? Diagnostics._0_was_exported_here
: Diagnostics._0_was_imported_here;
const unescapedName = unescapeLeadingUnderscores(name);
addRelatedInfo(
error(useSite, message, unescapedName),
createDiagnosticForNode(typeOnlyDeclaration, relatedMessage, unescapedName));
}
}
}
function getIsDeferredContext(location: Node, lastLocation: Node | undefined): boolean {
if (location.kind !== SyntaxKind.ArrowFunction && location.kind !== SyntaxKind.FunctionExpression) {
// initializers in instance property declaration of class like entities are executed in constructor and thus deferred
@@ -2055,9 +2081,7 @@ namespace ts {
if (symbol) {
error(
errorLocation,
isTypeOnlyEnumAlias(symbol)
? Diagnostics.Enum_0_cannot_be_used_as_a_value_because_only_its_type_has_been_imported
: Diagnostics.Cannot_use_namespace_0_as_a_value,
Diagnostics.Cannot_use_namespace_0_as_a_value,
unescapeLeadingUnderscores(name));
return true;
}
@@ -2146,11 +2170,14 @@ namespace ts {
return getSymbolOfPartOfRightHandSideOfImportEquals(node.moduleReference, dontResolveAlias);
}
function resolveExportByName(moduleSymbol: Symbol, name: __String, dontResolveAlias: boolean) {
function resolveExportByName(moduleSymbol: Symbol, name: __String, sourceNode: TypeOnlyCompatibleAliasDeclaration | undefined, dontResolveAlias: boolean) {
const exportValue = moduleSymbol.exports!.get(InternalSymbolName.ExportEquals);
return exportValue
? getPropertyOfType(getTypeOfSymbol(exportValue), name)
: resolveSymbol(moduleSymbol.exports!.get(name), dontResolveAlias);
if (exportValue) {
return getPropertyOfType(getTypeOfSymbol(exportValue), name);
}
const exportSymbol = moduleSymbol.exports!.get(name);
markSymbolOfAliasDeclarationIfResolvesToTypeOnly(sourceNode, exportSymbol);
return resolveSymbol(exportSymbol, dontResolveAlias);
}
function isSyntacticDefault(node: Node) {
@@ -2164,13 +2191,13 @@ namespace ts {
// Declaration files (and ambient modules)
if (!file || file.isDeclarationFile) {
// Definitely cannot have a synthetic default if they have a syntactic default member specified
const defaultExportSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, /*dontResolveAlias*/ true); // Dont resolve alias because we want the immediately exported symbol's declaration
const defaultExportSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, /*sourceNode*/ undefined, /*dontResolveAlias*/ true); // Dont resolve alias because we want the immediately exported symbol's declaration
if (defaultExportSymbol && some(defaultExportSymbol.declarations, isSyntacticDefault)) {
return false;
}
// It _might_ still be incorrect to assume there is no __esModule marker on the import at runtime, even if there is no `default` member
// So we check a bit more,
if (resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), dontResolveAlias)) {
if (resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), /*sourceNode*/ undefined, dontResolveAlias)) {
// If there is an `__esModule` specified in the declaration (meaning someone explicitly added it or wrote it in their code),
// it definitely is a module and does not have a synthetic default
return false;
@@ -2185,11 +2212,12 @@ namespace ts {
return hasExportAssignmentSymbol(moduleSymbol);
}
// JS files have a synthetic default if they do not contain ES2015+ module syntax (export = is not valid in js) _and_ do not have an __esModule marker
return !file.externalModuleIndicator && !resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), dontResolveAlias);
return !file.externalModuleIndicator && !resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), /*sourceNode*/ undefined, dontResolveAlias);
}
function getTargetOfImportClause(node: ImportClause, dontResolveAlias: boolean): Symbol | undefined {
const moduleSymbol = resolveExternalModuleName(node, node.parent.moduleSpecifier);
markSymbolOfAliasDeclarationIfTypeOnly(node);
if (moduleSymbol) {
let exportDefaultSymbol: Symbol | undefined;
@@ -2197,7 +2225,7 @@ namespace ts {
exportDefaultSymbol = moduleSymbol;
}
else {
exportDefaultSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, dontResolveAlias);
exportDefaultSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, node, dontResolveAlias);
}
const file = find(moduleSymbol.declarations, isSourceFile);
@@ -2232,25 +2260,16 @@ namespace ts {
}
else if (hasSyntheticDefault) {
// per emit behavior, a synthetic default overrides a "real" .default member if `__esModule` is not present
return maybeTypeOnly(
resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) ||
resolveSymbol(moduleSymbol, dontResolveAlias));
return resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias);
}
return maybeTypeOnly(exportDefaultSymbol);
}
function maybeTypeOnly(symbol: Symbol | undefined) {
if (symbol && node.isTypeOnly && node.name) {
return createTypeOnlyImportOrExport(node.name, symbol);
}
return symbol;
return exportDefaultSymbol;
}
}
function getTargetOfNamespaceImport(node: NamespaceImport, dontResolveAlias: boolean): Symbol | undefined {
const moduleSpecifier = node.parent.parent.moduleSpecifier;
const moduleSymbol = resolveESModuleSymbol(resolveExternalModuleName(node, moduleSpecifier), moduleSpecifier, dontResolveAlias, /*suppressUsageError*/ false);
return moduleSymbol && node.parent.isTypeOnly ? createTypeOnlySymbol(moduleSymbol) : moduleSymbol;
markSymbolOfAliasDeclarationIfTypeOnly(node);
return resolveESModuleSymbol(resolveExternalModuleName(node, moduleSpecifier), moduleSpecifier, dontResolveAlias, /*suppressUsageError*/ false);
}
function getTargetOfNamespaceExport(node: NamespaceExport, dontResolveAlias: boolean): Symbol | undefined {
@@ -2292,9 +2311,12 @@ namespace ts {
return result;
}
function getExportOfModule(symbol: Symbol, name: __String, dontResolveAlias: boolean): Symbol | undefined {
function getExportOfModule(symbol: Symbol, specifier: ImportOrExportSpecifier, dontResolveAlias: boolean): Symbol | undefined {
if (symbol.flags & SymbolFlags.Module) {
return resolveSymbol(getExportsOfSymbol(symbol).get(name)!, dontResolveAlias);
const name = (specifier.propertyName ?? specifier.name).escapedText;
const exportSymbol = getExportsOfSymbol(symbol).get(name);
markSymbolOfAliasDeclarationIfResolvesToTypeOnly(specifier, exportSymbol);
return resolveSymbol(exportSymbol, dontResolveAlias);
}
}
@@ -2329,8 +2351,7 @@ namespace ts {
// if symbolFromVariable is export - get its final target
symbolFromVariable = resolveSymbol(symbolFromVariable, dontResolveAlias);
let symbolFromModule = getExportOfModule(targetSymbol, name.escapedText, dontResolveAlias);
let symbolFromModule = getExportOfModule(targetSymbol, specifier, dontResolveAlias);
if (symbolFromModule === undefined && name.escapedText === InternalSymbolName.Default) {
const file = find(moduleSymbol.declarations, isSourceFile);
if (canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias)) {
@@ -2395,98 +2416,19 @@ namespace ts {
}
function getTargetOfImportSpecifier(node: ImportSpecifier, dontResolveAlias: boolean): Symbol | undefined {
const resolved = getExternalModuleMember(node.parent.parent.parent, node, dontResolveAlias);
if (resolved && node.parent.parent.isTypeOnly) {
return createTypeOnlyImportOrExport(node.name, resolved);
}
return resolved;
markSymbolOfAliasDeclarationIfTypeOnly(node);
return getExternalModuleMember(node.parent.parent.parent, node, dontResolveAlias);
}
function getTargetOfNamespaceExportDeclaration(node: NamespaceExportDeclaration, dontResolveAlias: boolean): Symbol {
return resolveExternalModuleSymbol(node.parent.symbol, dontResolveAlias);
}
/**
* Creates a type alias symbol with a target symbol for type-only imports and exports.
* The symbol for `A` in `export type { A }` or `export type { A } from "./mod"` has
* `TypeFlags.Alias` so that alias resolution works as usual, but once the target `A`
* has been resolved, we essentially want to pretend we have a type alias to that target.
*/
function createTypeOnlyImportOrExport(sourceNode: ExportSpecifier | Identifier, target: Symbol) {
const symbol = createTypeOnlySymbol(target);
if (!symbol && target !== unknownSymbol) {
const identifier = isExportSpecifier(sourceNode) ? sourceNode.name : sourceNode;
const nameText = idText(identifier);
const diagnostic = error(
identifier,
Diagnostics.Type_only_0_must_reference_a_type_but_1_is_a_value,
isExportSpecifier(sourceNode) ? "export" : "import",
nameText);
const targetDeclaration = target.valueDeclaration ?? target.declarations?.[0];
if (targetDeclaration) {
addRelatedInfo(diagnostic, createDiagnosticForNode(
targetDeclaration,
Diagnostics._0_is_declared_here,
nameText));
}
}
return symbol;
}
function createTypeOnlySymbol(target: Symbol): Symbol | undefined {
if (target.flags & SymbolFlags.ValueModule) {
return createNamespaceModuleForModule(target);
}
if (target.flags & SymbolFlags.Enum) {
return createNamespaceModuleForEnum(target);
}
if (!(target.flags & SymbolFlags.Value)) {
return target;
}
if (target.flags & SymbolFlags.Type) {
const alias = createSymbol(SymbolFlags.TypeAlias, target.escapedName);
alias.declarations = emptyArray;
alias.immediateTarget = target;
return alias;
}
}
function createNamespaceModuleForEnum(enumSymbol: Symbol) {
Debug.assert(!!(enumSymbol.flags & SymbolFlags.Enum));
const symbol = createSymbol(SymbolFlags.NamespaceModule | SymbolFlags.TypeAlias, enumSymbol.escapedName);
symbol.immediateTarget = enumSymbol;
symbol.declarations = enumSymbol.declarations;
if (enumSymbol.exports) {
symbol.exports = createSymbolTable();
enumSymbol.exports.forEach((exportSymbol, key) => {
symbol.exports!.set(key, Debug.assertDefined(createTypeOnlySymbol(exportSymbol)));
});
}
return symbol;
}
function createNamespaceModuleForModule(moduleSymbol: Symbol) {
Debug.assert(!!(moduleSymbol.flags & SymbolFlags.ValueModule));
const filtered = createSymbol(SymbolFlags.NamespaceModule, moduleSymbol.escapedName);
filtered.declarations = moduleSymbol.declarations;
if (moduleSymbol.exports) {
filtered.exports = createSymbolTable();
moduleSymbol.exports.forEach((exportSymbol, key) => {
const typeOnlyExport = createTypeOnlySymbol(exportSymbol);
if (typeOnlyExport) {
filtered.exports!.set(key, typeOnlyExport);
}
});
}
return filtered;
}
function getTargetOfExportSpecifier(node: ExportSpecifier, meaning: SymbolFlags, dontResolveAlias?: boolean) {
const target = node.parent.parent.moduleSpecifier ?
markSymbolOfAliasDeclarationIfTypeOnly(node);
return node.parent.parent.moduleSpecifier ?
getExternalModuleMember(node.parent.parent, node, dontResolveAlias) :
resolveEntityName(node.propertyName || node.name, meaning, /*ignoreErrors*/ false, dontResolveAlias);
return target && node.parent.parent.isTypeOnly ? createTypeOnlyImportOrExport(node, target) : target;
}
function getTargetOfExportAssignment(node: ExportAssignment | BinaryExpression, dontResolveAlias: boolean): Symbol | undefined {
@@ -2588,12 +2530,39 @@ namespace ts {
return links.target;
}
function markSymbolOfAliasDeclarationIfResolvesToTypeOnly(aliasDeclaration: TypeOnlyCompatibleAliasDeclaration | undefined, resolvesToSymbol: Symbol | undefined) {
if (!aliasDeclaration || !resolvesToSymbol) return;
const sourceSymbol = getSymbolOfNode(aliasDeclaration);
const links = getSymbolLinks(sourceSymbol);
if (links.typeOnlyDeclaration === undefined) {
const typeOnly = find(resolvesToSymbol.declarations, isTypeOnlyImportOrExportDeclaration);
links.typeOnlyDeclaration = typeOnly ?? getSymbolLinks(resolvesToSymbol).typeOnlyDeclaration ?? false;
}
}
function markSymbolOfAliasDeclarationIfTypeOnly(aliasDeclaration: TypeOnlyCompatibleAliasDeclaration) {
if (isTypeOnlyImportOrExportDeclaration(aliasDeclaration)) {
const symbol = getSymbolOfNode(aliasDeclaration);
const links = getSymbolLinks(symbol);
links.typeOnlyDeclaration = aliasDeclaration;
}
}
/** Indicates that a symbol directly or indirectly resolves to a type-only import or export. */
function getTypeOnlyAliasDeclaration(symbol: Symbol): TypeOnlyCompatibleAliasDeclaration | undefined {
if (!(symbol.flags & SymbolFlags.Alias)) {
return undefined;
}
const links = getSymbolLinks(symbol);
return links.typeOnlyDeclaration || undefined;
}
function markExportAsReferenced(node: ImportEqualsDeclaration | ExportSpecifier) {
const symbol = getSymbolOfNode(node);
const target = resolveAlias(symbol);
if (target) {
const markAlias = target === unknownSymbol ||
((target.flags & SymbolFlags.Value) && !isConstEnumOrConstEnumOnlyModule(target));
((target.flags & SymbolFlags.Value) && !isConstEnumOrConstEnumOnlyModule(target) && !getTypeOnlyAliasDeclaration(symbol));
if (markAlias) {
markAliasSymbolAsReferenced(symbol);
@@ -2623,6 +2592,15 @@ namespace ts {
}
}
// Aliases that resolve to const enums are not marked as referenced because they are not emitted,
// but their usage in value positions must be tracked to determine if the import can be type-only.
function markConstEnumAliasAsReferenced(symbol: Symbol) {
const links = getSymbolLinks(symbol);
if (!links.constEnumReferenced) {
links.constEnumReferenced = true;
}
}
// This function is only for imports with entity names
function getSymbolOfPartOfRightHandSideOfImportEquals(entityName: EntityName, dontResolveAlias?: boolean): Symbol | undefined {
// There are three things we might try to look for. In the following examples,
@@ -2705,6 +2683,9 @@ namespace ts {
throw Debug.assertNever(name, "Unknown entity name kind.");
}
Debug.assert((getCheckFlags(symbol) & CheckFlags.Instantiated) === 0, "Should never get an instantiated symbol here.");
if (isIdentifier(name) && symbol.flags & SymbolFlags.Alias) {
markSymbolOfAliasDeclarationIfResolvesToTypeOnly(getTypeOnlyCompatibleAliasDeclarationFromName(name), symbol);
}
return (symbol.flags & meaning) || dontResolveAlias ? symbol : resolveAlias(symbol);
}
@@ -3267,7 +3248,7 @@ namespace ts {
}
function symbolIsValue(symbol: Symbol): boolean {
return !!(symbol.flags & SymbolFlags.Value || symbol.flags & SymbolFlags.Alias && resolveAlias(symbol).flags & SymbolFlags.Value);
return !!(symbol.flags & SymbolFlags.Value || symbol.flags & SymbolFlags.Alias && resolveAlias(symbol).flags & SymbolFlags.Value && !getTypeOnlyAliasDeclaration(symbol));
}
function findConstructorDeclaration(node: ClassLikeDeclaration): ConstructorDeclaration | undefined {
@@ -8301,20 +8282,10 @@ namespace ts {
return errorType;
}
let type: Type;
let declaration;
if (isTypeOnlyAlias(symbol)) {
// Symbol is synthetic type alias for type-only import or export.
// See `createSyntheticTypeAlias`.
type = getDeclaredTypeOfSymbol(symbol.immediateTarget);
declaration = symbol.valueDeclaration;
}
else {
declaration = Debug.assertDefined(find(symbol.declarations, isTypeAlias), "Type alias symbol with no valid declaration found");
const typeNode = isJSDocTypeAlias(declaration) ? declaration.typeExpression : declaration.type;
// If typeNode is missing, we will error in checkJSDocTypedefTag.
type = typeNode ? getTypeFromTypeNode(typeNode) : errorType;
}
const declaration = Debug.assertDefined(find(symbol.declarations, isTypeAlias), "Type alias symbol with no valid declaration found");
const typeNode = isJSDocTypeAlias(declaration) ? declaration.typeExpression : declaration.type;
// If typeNode is missing, we will error in checkJSDocTypedefTag.
let type = typeNode ? getTypeFromTypeNode(typeNode) : errorType;
if (popTypeResolution()) {
const typeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
@@ -11045,9 +11016,6 @@ namespace ts {
if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
return getTypeFromClassOrInterfaceReference(node, symbol);
}
if (isTypeOnlyAlias(symbol)) {
return getTypeReferenceType(node, symbol.immediateTarget);
}
if (symbol.flags & SymbolFlags.TypeAlias) {
return getTypeFromTypeAliasReference(node, symbol);
}
@@ -20306,8 +20274,13 @@ namespace ts {
}
function markAliasReferenced(symbol: Symbol, location: Node) {
if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !isInTypeQuery(location) && ((compilerOptions.preserveConstEnums && isExportOrExportExpression(location)) || !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol)))) {
markAliasSymbolAsReferenced(symbol);
if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !isInTypeQuery(location) && !getTypeOnlyAliasDeclaration(symbol)) {
if (compilerOptions.preserveConstEnums && isExportOrExportExpression(location) || !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) {
markAliasSymbolAsReferenced(symbol);
}
else {
markConstEnumAliasAsReferenced(symbol);
}
}
}
@@ -22866,7 +22839,7 @@ namespace ts {
reactSym.isReferenced = SymbolFlags.All;
// If react symbol is alias, mark it as refereced
if (reactSym.flags & SymbolFlags.Alias) {
if (reactSym.flags & SymbolFlags.Alias && !getTypeOnlyAliasDeclaration(reactSym)) {
markAliasSymbolAsReferenced(reactSym);
}
}
@@ -29673,7 +29646,8 @@ namespace ts {
if (rootSymbol
&& rootSymbol.flags & SymbolFlags.Alias
&& symbolIsValue(rootSymbol)
&& !isConstEnumOrConstEnumOnlyModule(resolveAlias(rootSymbol))) {
&& !isConstEnumOrConstEnumOnlyModule(resolveAlias(rootSymbol))
&& !getTypeOnlyAliasDeclaration(rootSymbol)) {
markAliasSymbolAsReferenced(rootSymbol);
}
}
@@ -33129,17 +33103,15 @@ namespace ts {
}
function importClauseContainsReferencedImport(importClause: ImportClause) {
return importClause.name && isReferenced(importClause)
|| importClause.namedBindings && namedBindingsContainsReferencedImport(importClause.namedBindings);
return forEachImportClauseDeclaration(importClause, declaration => {
return !!getSymbolOfNode(declaration).isReferenced;
});
}
function isReferenced(declaration: Declaration) {
return !!getMergedSymbol(getSymbolOfNode(declaration)).isReferenced;
}
function namedBindingsContainsReferencedImport(namedBindings: NamedImportBindings) {
return isNamespaceImport(namedBindings)
? isReferenced(namedBindings)
: some(namedBindings.elements, isReferenced);
}
function importClauseContainsConstEnumUsedAsValue(importClause: ImportClause) {
return forEachImportClauseDeclaration(importClause, declaration => {
return !!getSymbolLinks(getSymbolOfNode(declaration)).constEnumReferenced;
});
}
function checkImportsForTypeOnlyConversion(sourceFile: SourceFile) {
@@ -33149,15 +33121,12 @@ namespace ts {
statement.importClause &&
!statement.importClause.isTypeOnly &&
importClauseContainsReferencedImport(statement.importClause) &&
!isReferencedAliasDeclaration(statement.importClause, /*checkChildren*/ true)
!isReferencedAliasDeclaration(statement.importClause, /*checkChildren*/ true) &&
!importClauseContainsConstEnumUsedAsValue(statement.importClause)
) {
const isError = compilerOptions.importsNotUsedAsValues === importsNotUsedAsValues.Error;
errorOrSuggestion(
isError,
error(
statement,
isError
? Diagnostics.This_import_is_never_used_as_a_value_and_must_use_import_type_because_the_importsNotUsedAsValues_is_set_to_error
: Diagnostics.This_import_may_be_converted_to_a_type_only_import);
Diagnostics.This_import_is_never_used_as_a_value_and_must_use_import_type_because_the_importsNotUsedAsValues_is_set_to_error);
}
}
}
@@ -33654,7 +33623,10 @@ namespace ts {
});
}
if (!node.isDeclarationFile && isExternalModule(node)) {
if (compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Error &&
!node.isDeclarationFile &&
isExternalModule(node)
) {
checkImportsForTypeOnlyConversion(node);
}
@@ -34245,7 +34217,7 @@ namespace ts {
if (isDeclarationNameOrImportPropertyName(node)) {
const symbol = getSymbolAtLocation(node);
if (symbol) {
return isTypeOnlyImportOrExportName(node) ? getDeclaredTypeOfSymbol(symbol) : getTypeOfSymbol(symbol);
return getTypeOfSymbol(symbol);
}
return errorType;
}
@@ -34486,7 +34458,7 @@ namespace ts {
const symbol = getReferencedValueSymbol(node);
// We should only get the declaration of an alias if there isn't a local value
// declaration for the symbol
if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value)) {
if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !getTypeOnlyAliasDeclaration(symbol)) {
return getDeclarationOfAliasSymbol(symbol);
}
}
@@ -34576,11 +34548,13 @@ namespace ts {
function isValueAliasDeclaration(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.ImportEqualsDeclaration:
return isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol);
case SyntaxKind.ImportClause:
case SyntaxKind.NamespaceImport:
case SyntaxKind.ImportSpecifier:
case SyntaxKind.ExportSpecifier:
return isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol);
const symbol = getSymbolOfNode(node) || unknownSymbol;
return isAliasResolvedToValue(symbol) && !getTypeOnlyAliasDeclaration(symbol);
case SyntaxKind.ExportDeclaration:
const exportClause = (<ExportDeclaration>node).exportClause;
return !!exportClause && (
@@ -34629,7 +34603,8 @@ namespace ts {
}
const target = getSymbolLinks(symbol!).target; // TODO: GH#18217
if (target && getModifierFlags(node) & ModifierFlags.Export &&
target.flags & SymbolFlags.Value && (compilerOptions.preserveConstEnums || !isConstEnumOrConstEnumOnlyModule(target))) {
target.flags & SymbolFlags.Value &&
(compilerOptions.preserveConstEnums || !isConstEnumOrConstEnumOnlyModule(target))) {
// An `export import ... =` of a value symbol is always considered referenced
return true;
}
+3 -3
View File
@@ -475,9 +475,9 @@ namespace ts {
{
name: "importsNotUsedAsValues",
type: createMapFromTemplate({
remove: importsNotUsedAsValues.Remove,
preserve: importsNotUsedAsValues.Preserve,
error: importsNotUsedAsValues.Error
remove: ImportsNotUsedAsValues.Remove,
preserve: ImportsNotUsedAsValues.Preserve,
error: ImportsNotUsedAsValues.Error
}),
affectsEmit: true,
affectsSemanticDiagnostics: true,
+15 -7
View File
@@ -1055,11 +1055,15 @@
"category": "Error",
"code": 1359
},
"Type-only {0} must reference a type, but '{1}' is a value.": {
"Did you mean to parenthesize this function type?": {
"category": "Error",
"code": 1360
},
"'{0}' cannot be used as a value because it was imported using 'import type'.": {
"category": "Error",
"code": 1361
},
"Enum '{0}' cannot be used as a value because only its type has been imported.": {
"'{0}' cannot be used as a value because it was exported using 'export type'.": {
"category": "Error",
"code": 1362
},
@@ -1099,10 +1103,6 @@
"category": "Error",
"code": 1371
},
"This import may be converted to a type-only import.": {
"category": "Suggestion",
"code": 1372
},
"Convert to type-only import": {
"category": "Message",
"code": 1373
@@ -1115,9 +1115,17 @@
"category": "Error",
"code": 1375
},
"'{0}' was imported here.": {
"category": "Message",
"code": 1376
},
"'{0}' was exported here.": {
"category": "Message",
"code": 1377
},
"Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.": {
"category": "Error",
"code": 1376
"code": 1378
},
"The types of '{0}' are incompatible between these types.": {
"category": "Error",
+3 -3
View File
@@ -2778,8 +2778,8 @@ namespace ts {
// Elide the declaration if the import clause was elided.
const importClause = visitNode(node.importClause, visitImportClause, isImportClause);
return importClause ||
compilerOptions.importsNotUsedAsValues === importsNotUsedAsValues.Preserve ||
compilerOptions.importsNotUsedAsValues === importsNotUsedAsValues.Error
compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Preserve ||
compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Error
? updateImportDeclaration(
node,
/*decorators*/ undefined,
@@ -2931,7 +2931,7 @@ namespace ts {
if (isExternalModuleImportEqualsDeclaration(node)) {
const isReferenced = resolver.isReferencedAliasDeclaration(node);
// If the alias is unreferenced but we want to keep the import, replace with 'import "mod"'.
if (!isReferenced && compilerOptions.importsNotUsedAsValues === importsNotUsedAsValues.Preserve) {
if (!isReferenced && compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Preserve) {
return setOriginalNode(
setTextRange(
createImportDeclaration(
+6 -3
View File
@@ -2538,6 +2538,7 @@ namespace ts {
}
export type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier;
export type TypeOnlyCompatibleAliasDeclaration = ImportClause | NamespaceImport | ImportOrExportSpecifier;
/**
* This is either an `export =` or an `export default` declaration.
@@ -4062,7 +4063,8 @@ namespace ts {
instantiations?: Map<Type>; // Instantiations of generic type alias (undefined if non-generic)
inferredClassSymbol?: Map<TransientSymbol>; // Symbol of an inferred ES5 constructor function
mapper?: TypeMapper; // Type mapper for instantiation alias
referenced?: boolean; // True if alias symbol has been referenced as a value
referenced?: boolean; // True if alias symbol has been referenced as a value that can be emitted
constEnumReferenced?: boolean; // True if alias symbol resolves to a const enum and is referenced as a value ('referenced' will be false)
containingType?: UnionOrIntersectionType; // Containing union or intersection type for synthetic property
leftSpread?: Symbol; // Left source for synthetic spread property
rightSpread?: Symbol; // Right source for synthetic spread property
@@ -4085,6 +4087,7 @@ namespace ts {
deferralConstituents?: Type[]; // Calculated list of constituents for a deferred type
deferralParent?: Type; // Source union/intersection of a deferred type
cjsExportMerged?: Symbol; // Version of the symbol with all non export= exports merged with the export= target
typeOnlyDeclaration?: TypeOnlyCompatibleAliasDeclaration | false; // First resolved alias declaration that makes the symbol only usable in type constructs
}
/* @internal */
@@ -5046,7 +5049,7 @@ namespace ts {
/*@internal*/generateCpuProfile?: string;
/*@internal*/help?: boolean;
importHelpers?: boolean;
importsNotUsedAsValues?: importsNotUsedAsValues;
importsNotUsedAsValues?: ImportsNotUsedAsValues;
/*@internal*/init?: boolean;
inlineSourceMap?: boolean;
inlineSources?: boolean;
@@ -5168,7 +5171,7 @@ namespace ts {
ReactNative = 3
}
export const enum importsNotUsedAsValues {
export const enum ImportsNotUsedAsValues {
Remove,
Preserve,
Error
+44 -8
View File
@@ -44,14 +44,6 @@ namespace ts {
return (symbol.flags & SymbolFlags.Transient) !== 0;
}
export function isTypeOnlyAlias(symbol: Symbol): symbol is TransientSymbol & { immediateTarget: Symbol } {
return isTransientSymbol(symbol) && !!symbol.immediateTarget;
}
export function isTypeOnlyEnumAlias(symbol: Symbol): ReturnType<typeof isTypeOnlyAlias> {
return isTypeOnlyAlias(symbol) && !!(symbol.immediateTarget.flags & SymbolFlags.Enum);
}
const stringWriter = createSingleLineStringWriter();
function createSingleLineStringWriter(): EmitTextWriter {
@@ -1779,6 +1771,27 @@ namespace ts {
}
}
export function isPartOfTypeQuery(node: Node) {
while (node.kind === SyntaxKind.QualifiedName || node.kind === SyntaxKind.Identifier) {
node = node.parent;
}
return node.kind === SyntaxKind.TypeQuery;
}
export function isPartOfPossiblyValidTypeOrAbstractComputedPropertyName(node: Node) {
while (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.PropertyAccessExpression) {
node = node.parent;
}
if (node.kind !== SyntaxKind.ComputedPropertyName) {
return false;
}
if (hasModifier(node.parent, ModifierFlags.Abstract)) {
return true;
}
const containerKind = node.parent.parent.kind;
return containerKind === SyntaxKind.InterfaceDeclaration || containerKind === SyntaxKind.TypeLiteral;
}
export function isExternalModuleImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration & { moduleReference: ExternalModuleReference } {
return node.kind === SyntaxKind.ImportEqualsDeclaration && (<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference;
}
@@ -2285,6 +2298,19 @@ namespace ts {
return node.kind === SyntaxKind.ImportDeclaration && !!node.importClause && !!node.importClause.name;
}
export function forEachImportClauseDeclaration<T>(node: ImportClause, action: (declaration: ImportClause | NamespaceImport | ImportSpecifier) => T | undefined): T | undefined {
if (node.name) {
const result = action(node);
if (result) return result;
}
if (node.namedBindings) {
const result = isNamespaceImport(node.namedBindings)
? action(node.namedBindings)
: forEach(node.namedBindings.elements, action);
if (result) return result;
}
}
export function hasQuestionToken(node: Node) {
if (node) {
switch (node.kind) {
@@ -2734,6 +2760,16 @@ namespace ts {
node.kind === SyntaxKind.PropertyAssignment && isAliasableExpression((node as PropertyAssignment).initializer);
}
export function getTypeOnlyCompatibleAliasDeclarationFromName(node: Identifier): TypeOnlyCompatibleAliasDeclaration | undefined {
switch (node.parent.kind) {
case SyntaxKind.ImportClause:
case SyntaxKind.ImportSpecifier:
case SyntaxKind.NamespaceImport:
case SyntaxKind.ExportSpecifier:
return node.parent as TypeOnlyCompatibleAliasDeclaration;
}
}
function isAliasableExpression(e: Expression) {
return isEntityNameExpression(e) || isClassExpression(e);
}
+6 -7
View File
@@ -1721,16 +1721,15 @@ namespace ts {
return isImportSpecifier(node) || isExportSpecifier(node);
}
export function isTypeOnlyImportOrExportName(node: Node): boolean {
if (node.kind !== SyntaxKind.Identifier) {
return false;
}
switch (node.parent.kind) {
export function isTypeOnlyImportOrExportDeclaration(node: Node): node is TypeOnlyCompatibleAliasDeclaration {
switch (node.kind) {
case SyntaxKind.ImportSpecifier:
case SyntaxKind.ExportSpecifier:
return (node.parent as ImportSpecifier | ExportSpecifier).parent.parent.isTypeOnly;
return (node as ImportOrExportSpecifier).parent.parent.isTypeOnly;
case SyntaxKind.NamespaceImport:
return (node as NamespaceImport).parent.isTypeOnly;
case SyntaxKind.ImportClause:
return (node.parent as ImportClause).isTypeOnly;
return (node as ImportClause).isTypeOnly;
default:
return false;
}
-9
View File
@@ -2,10 +2,6 @@
namespace ts.SymbolDisplay {
// TODO(drosen): use contextual SemanticMeaning.
export function getSymbolKind(typeChecker: TypeChecker, symbol: Symbol, location: Node): ScriptElementKind {
while (isTypeOnlyAlias(symbol)) {
symbol = symbol.immediateTarget;
}
const result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location);
if (result !== ScriptElementKind.unknown) {
return result;
@@ -125,11 +121,6 @@ namespace ts.SymbolDisplay {
// TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location
export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: TypeChecker, symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node | undefined,
location: Node, semanticMeaning = getMeaningFromLocation(location), alias?: Symbol): SymbolDisplayPartsDocumentationAndSymbolKind {
while (isTypeOnlyAlias(symbol)) {
symbol = symbol.immediateTarget;
}
const displayParts: SymbolDisplayPart[] = [];
let documentation: SymbolDisplayPart[] = [];
let tags: JSDocTagInfo[] = [];
+25
View File
@@ -0,0 +1,25 @@
//// [tests/cases/conformance/externalModules/typeOnly/ambient.ts] ////
//// [a.ts]
export class A { a!: string }
//// [b.ts]
import type { A } from './a';
declare class B extends A {}
declare namespace ns {
class C extends A {}
}
//// [a.js]
"use strict";
exports.__esModule = true;
var A = /** @class */ (function () {
function A() {
}
return A;
}());
exports.A = A;
//// [b.js]
"use strict";
exports.__esModule = true;
+21
View File
@@ -0,0 +1,21 @@
=== /a.ts ===
export class A { a!: string }
>A : Symbol(A, Decl(a.ts, 0, 0))
>a : Symbol(A.a, Decl(a.ts, 0, 16))
=== /b.ts ===
import type { A } from './a';
>A : Symbol(A, Decl(b.ts, 0, 13))
declare class B extends A {}
>B : Symbol(B, Decl(b.ts, 0, 29))
>A : Symbol(A, Decl(b.ts, 0, 13))
declare namespace ns {
>ns : Symbol(ns, Decl(b.ts, 1, 28))
class C extends A {}
>C : Symbol(C, Decl(b.ts, 2, 22))
>A : Symbol(A, Decl(b.ts, 0, 13))
}
+21
View File
@@ -0,0 +1,21 @@
=== /a.ts ===
export class A { a!: string }
>A : A
>a : string
=== /b.ts ===
import type { A } from './a';
>A : A
declare class B extends A {}
>B : B
>A : A
declare namespace ns {
>ns : typeof ns
class C extends A {}
>C : C
>A : A
}
+4 -3
View File
@@ -1547,6 +1547,7 @@ declare namespace ts {
name: Identifier;
}
export type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier;
export type TypeOnlyCompatibleAliasDeclaration = ImportClause | NamespaceImport | ImportOrExportSpecifier;
/**
* This is either an `export =` or an `export default` declaration.
* Unless `isExportEquals` is set, this node was parsed as an `export default`.
@@ -2651,7 +2652,7 @@ declare namespace ts {
experimentalDecorators?: boolean;
forceConsistentCasingInFileNames?: boolean;
importHelpers?: boolean;
importsNotUsedAsValues?: importsNotUsedAsValues;
importsNotUsedAsValues?: ImportsNotUsedAsValues;
inlineSourceMap?: boolean;
inlineSources?: boolean;
isolatedModules?: boolean;
@@ -2750,7 +2751,7 @@ declare namespace ts {
React = 2,
ReactNative = 3
}
export enum importsNotUsedAsValues {
export enum ImportsNotUsedAsValues {
Remove = 0,
Preserve = 1,
Error = 2
@@ -3739,7 +3740,7 @@ declare namespace ts {
function isTemplateLiteralToken(node: Node): node is TemplateLiteralToken;
function isTemplateMiddleOrTemplateTail(node: Node): node is TemplateMiddle | TemplateTail;
function isImportOrExportSpecifier(node: Node): node is ImportSpecifier | ExportSpecifier;
function isTypeOnlyImportOrExportName(node: Node): boolean;
function isTypeOnlyImportOrExportDeclaration(node: Node): node is TypeOnlyCompatibleAliasDeclaration;
function isStringTextContainingNode(node: Node): node is StringLiteral | TemplateLiteralToken;
function isModifier(node: Node): node is Modifier;
function isEntityName(node: Node): node is EntityName;
+4 -3
View File
@@ -1547,6 +1547,7 @@ declare namespace ts {
name: Identifier;
}
export type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier;
export type TypeOnlyCompatibleAliasDeclaration = ImportClause | NamespaceImport | ImportOrExportSpecifier;
/**
* This is either an `export =` or an `export default` declaration.
* Unless `isExportEquals` is set, this node was parsed as an `export default`.
@@ -2651,7 +2652,7 @@ declare namespace ts {
experimentalDecorators?: boolean;
forceConsistentCasingInFileNames?: boolean;
importHelpers?: boolean;
importsNotUsedAsValues?: importsNotUsedAsValues;
importsNotUsedAsValues?: ImportsNotUsedAsValues;
inlineSourceMap?: boolean;
inlineSources?: boolean;
isolatedModules?: boolean;
@@ -2750,7 +2751,7 @@ declare namespace ts {
React = 2,
ReactNative = 3
}
export enum importsNotUsedAsValues {
export enum ImportsNotUsedAsValues {
Remove = 0,
Preserve = 1,
Error = 2
@@ -3739,7 +3740,7 @@ declare namespace ts {
function isTemplateLiteralToken(node: Node): node is TemplateLiteralToken;
function isTemplateMiddleOrTemplateTail(node: Node): node is TemplateMiddle | TemplateTail;
function isImportOrExportSpecifier(node: Node): node is ImportSpecifier | ExportSpecifier;
function isTypeOnlyImportOrExportName(node: Node): boolean;
function isTypeOnlyImportOrExportDeclaration(node: Node): node is TypeOnlyCompatibleAliasDeclaration;
function isStringTextContainingNode(node: Node): node is StringLiteral | TemplateLiteralToken;
function isModifier(node: Node): node is Modifier;
function isEntityName(node: Node): node is EntityName;
@@ -13,7 +13,7 @@ tests/cases/compiler/awaitInNonAsyncFunction.ts(31,5): error TS1308: 'await' exp
tests/cases/compiler/awaitInNonAsyncFunction.ts(34,7): error TS1103: A 'for-await-of' statement is only allowed within an async function or async generator.
tests/cases/compiler/awaitInNonAsyncFunction.ts(35,5): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules.
tests/cases/compiler/awaitInNonAsyncFunction.ts(39,5): error TS1103: A 'for-await-of' statement is only allowed within an async function or async generator.
tests/cases/compiler/awaitInNonAsyncFunction.ts(40,1): error TS1376: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.
tests/cases/compiler/awaitInNonAsyncFunction.ts(40,1): error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.
==== tests/cases/compiler/awaitInNonAsyncFunction.ts (16 errors) ====
@@ -100,4 +100,4 @@ tests/cases/compiler/awaitInNonAsyncFunction.ts(40,1): error TS1376: Top-level '
!!! error TS1103: A 'for-await-of' statement is only allowed within an async function or async generator.
await null;
~~~~~
!!! error TS1376: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.
!!! error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.
+3 -2
View File
@@ -1,4 +1,4 @@
/d.ts(2,5): error TS2693: 'D' only refers to a type, but is being used as a value here.
/d.ts(2,5): error TS1361: 'D' cannot be used as a value because it was imported using 'import type'.
/d.ts(3,7): error TS2741: Property 'a' is missing in type '{}' but required in type 'A'.
@@ -19,7 +19,8 @@
import { D } from './c';
new D();
~
!!! error TS2693: 'D' only refers to a type, but is being used as a value here.
!!! error TS1361: 'D' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 /c.ts:1:15: 'D' was imported here.
const d: D = {};
~
!!! error TS2741: Property 'a' is missing in type '{}' but required in type 'A'.
+3 -1
View File
@@ -4,7 +4,7 @@ class A { a!: string }
>a : Symbol(A.a, Decl(a.ts, 0, 9))
export type { A as B };
>A : Symbol(A)
>A : Symbol(A, Decl(a.ts, 0, 0))
>B : Symbol(B, Decl(a.ts, 1, 13))
export type Z = A;
@@ -33,6 +33,8 @@ import { D } from './c';
>D : Symbol(D, Decl(d.ts, 0, 8))
new D();
>D : Symbol(D, Decl(d.ts, 0, 8))
const d: D = {};
>d : Symbol(d, Decl(d.ts, 2, 5))
>D : Symbol(D, Decl(d.ts, 0, 8))
+10 -10
View File
@@ -4,7 +4,7 @@ class A { a!: string }
>a : string
export type { A as B };
>A : A
>A : typeof A
>B : A
export type Z = A;
@@ -16,26 +16,26 @@ import { Z as Y } from './a';
>Y : any
export { B as C } from './a';
>B : any
>C : any
>B : typeof import("/a").B
>C : typeof import("/a").B
=== /c.ts ===
import type { C } from './b';
>C : A
>C : C
export { C as D };
>C : any
>D : any
>C : typeof C
>D : typeof C
=== /d.ts ===
import { D } from './c';
>D : any
>D : typeof D
new D();
>new D() : any
>D : any
>new D() : D
>D : typeof D
const d: D = {};
>d : A
>d : D
>{} : {}
@@ -0,0 +1,36 @@
/d.ts(2,11): error TS2339: Property 'A' does not exist on type 'typeof import("/b")'.
/d.ts(3,11): error TS2339: Property 'B' does not exist on type 'typeof import("/b")'.
/d.ts(4,7): error TS2741: Property 'a' is missing in type '{}' but required in type 'A'.
/d.ts(5,7): error TS2741: Property 'a' is missing in type '{}' but required in type 'A'.
==== /a.ts (0 errors) ====
class A { a!: string }
export type { A as default };
==== /b.ts (0 errors) ====
import A from './a';
import type { default as B } from './a';
export { A, B };
==== /c.ts (0 errors) ====
import * as types from './b';
export { types as default };
==== /d.ts (4 errors) ====
import types from './c';
new types.A();
~
!!! error TS2339: Property 'A' does not exist on type 'typeof import("/b")'.
new types.B();
~
!!! error TS2339: Property 'B' does not exist on type 'typeof import("/b")'.
const a: types.A = {};
~
!!! error TS2741: Property 'a' is missing in type '{}' but required in type 'A'.
!!! related TS2728 /a.ts:1:11: 'a' is declared here.
const b: types.B = {};
~
!!! error TS2741: Property 'a' is missing in type '{}' but required in type 'A'.
!!! related TS2728 /a.ts:1:11: 'a' is declared here.
+47
View File
@@ -0,0 +1,47 @@
//// [tests/cases/conformance/externalModules/typeOnly/chained2.ts] ////
//// [a.ts]
class A { a!: string }
export type { A as default };
//// [b.ts]
import A from './a';
import type { default as B } from './a';
export { A, B };
//// [c.ts]
import * as types from './b';
export { types as default };
//// [d.ts]
import types from './c';
new types.A();
new types.B();
const a: types.A = {};
const b: types.B = {};
//// [a.js]
"use strict";
exports.__esModule = true;
var A = /** @class */ (function () {
function A() {
}
return A;
}());
//// [b.js]
"use strict";
exports.__esModule = true;
//// [c.js]
"use strict";
exports.__esModule = true;
var types = require("./b");
exports["default"] = types;
//// [d.js]
"use strict";
exports.__esModule = true;
var c_1 = require("./c");
new c_1["default"].A();
new c_1["default"].B();
var a = {};
var b = {};
@@ -0,0 +1,49 @@
=== /a.ts ===
class A { a!: string }
>A : Symbol(A, Decl(a.ts, 0, 0))
>a : Symbol(A.a, Decl(a.ts, 0, 9))
export type { A as default };
>A : Symbol(A, Decl(a.ts, 0, 0))
>default : Symbol(default, Decl(a.ts, 1, 13))
=== /b.ts ===
import A from './a';
>A : Symbol(A, Decl(b.ts, 0, 6))
import type { default as B } from './a';
>default : Symbol(default, Decl(a.ts, 1, 13))
>B : Symbol(B, Decl(b.ts, 1, 13))
export { A, B };
>A : Symbol(A, Decl(b.ts, 2, 8))
>B : Symbol(B, Decl(b.ts, 2, 11))
=== /c.ts ===
import * as types from './b';
>types : Symbol(types, Decl(c.ts, 0, 6))
export { types as default };
>types : Symbol(types, Decl(c.ts, 0, 6))
>default : Symbol(default, Decl(c.ts, 1, 8))
=== /d.ts ===
import types from './c';
>types : Symbol(types, Decl(d.ts, 0, 6))
new types.A();
>types : Symbol(types, Decl(d.ts, 0, 6))
new types.B();
>types : Symbol(types, Decl(d.ts, 0, 6))
const a: types.A = {};
>a : Symbol(a, Decl(d.ts, 3, 5))
>types : Symbol(types, Decl(d.ts, 0, 6))
>A : Symbol(types.A, Decl(b.ts, 2, 8))
const b: types.B = {};
>b : Symbol(b, Decl(d.ts, 4, 5))
>types : Symbol(types, Decl(d.ts, 0, 6))
>B : Symbol(types.B, Decl(b.ts, 2, 11))
+55
View File
@@ -0,0 +1,55 @@
=== /a.ts ===
class A { a!: string }
>A : A
>a : string
export type { A as default };
>A : typeof A
>default : A
=== /b.ts ===
import A from './a';
>A : typeof A
import type { default as B } from './a';
>default : typeof A
>B : A
export { A, B };
>A : typeof A
>B : typeof A
=== /c.ts ===
import * as types from './b';
>types : typeof types
export { types as default };
>types : typeof types
>default : typeof types
=== /d.ts ===
import types from './c';
>types : typeof types
new types.A();
>new types.A() : any
>types.A : any
>types : typeof types
>A : any
new types.B();
>new types.B() : any
>types.B : any
>types : typeof types
>B : any
const a: types.A = {};
>a : types.A
>types : any
>{} : {}
const b: types.B = {};
>b : types.A
>types : any
>{} : {}
@@ -0,0 +1,60 @@
tests/cases/conformance/externalModules/typeOnly/component.ts(12,4): error TS1361: 'onInit' cannot be used as a value because it was imported using 'import type'.
tests/cases/conformance/externalModules/typeOnly/component.ts(16,4): error TS1361: 'onInit' cannot be used as a value because it was imported using 'import type'.
tests/cases/conformance/externalModules/typeOnly/component.ts(20,4): error TS1361: 'onInit' cannot be used as a value because it was imported using 'import type'.
tests/cases/conformance/externalModules/typeOnly/component.ts(24,4): error TS1361: 'onInit' cannot be used as a value because it was imported using 'import type'.
==== tests/cases/conformance/externalModules/typeOnly/framework-hooks.ts (0 errors) ====
export const onInit = Symbol("onInit");
==== tests/cases/conformance/externalModules/typeOnly/component.ts (4 errors) ====
import type { onInit } from "./framework-hooks";
interface Component {
[onInit]?(): void;
}
type T = {
[onInit]: any;
}
const o = {
[onInit]: 0 // Error
~~~~~~
!!! error TS1361: 'onInit' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 tests/cases/conformance/externalModules/typeOnly/component.ts:1:15: 'onInit' was imported here.
};
class C {
[onInit]: any; // Error (because class fields)
~~~~~~
!!! error TS1361: 'onInit' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 tests/cases/conformance/externalModules/typeOnly/component.ts:1:15: 'onInit' was imported here.
}
class D {
[onInit] = 0; // Error
~~~~~~
!!! error TS1361: 'onInit' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 tests/cases/conformance/externalModules/typeOnly/component.ts:1:15: 'onInit' was imported here.
}
class E {
[onInit]() {} // Error
~~~~~~
!!! error TS1361: 'onInit' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 tests/cases/conformance/externalModules/typeOnly/component.ts:1:15: 'onInit' was imported here.
}
abstract class F {
abstract [onInit](): void;
}
class G {
declare [onInit]: any;
}
declare class H {
[onInit]: any;
}
@@ -0,0 +1,67 @@
//// [tests/cases/conformance/externalModules/typeOnly/computedPropertyName.ts] ////
//// [framework-hooks.ts]
export const onInit = Symbol("onInit");
//// [component.ts]
import type { onInit } from "./framework-hooks";
interface Component {
[onInit]?(): void;
}
type T = {
[onInit]: any;
}
const o = {
[onInit]: 0 // Error
};
class C {
[onInit]: any; // Error (because class fields)
}
class D {
[onInit] = 0; // Error
}
class E {
[onInit]() {} // Error
}
abstract class F {
abstract [onInit](): void;
}
class G {
declare [onInit]: any;
}
declare class H {
[onInit]: any;
}
//// [framework-hooks.js]
export const onInit = Symbol("onInit");
//// [component.js]
var _a;
const o = {
[onInit]: 0 // Error
};
class C {
}
class D {
constructor() {
this[_a] = 0; // Error
}
}
_a = onInit;
class E {
[onInit]() { } // Error
}
class F {
}
class G {
}
@@ -0,0 +1,82 @@
=== tests/cases/conformance/externalModules/typeOnly/framework-hooks.ts ===
export const onInit = Symbol("onInit");
>onInit : Symbol(onInit, Decl(framework-hooks.ts, 0, 12))
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
=== tests/cases/conformance/externalModules/typeOnly/component.ts ===
import type { onInit } from "./framework-hooks";
>onInit : Symbol(onInit, Decl(component.ts, 0, 13))
interface Component {
>Component : Symbol(Component, Decl(component.ts, 0, 48))
[onInit]?(): void;
>[onInit] : Symbol(Component[onInit], Decl(component.ts, 2, 21))
>onInit : Symbol(onInit, Decl(component.ts, 0, 13))
}
type T = {
>T : Symbol(T, Decl(component.ts, 4, 1))
[onInit]: any;
>[onInit] : Symbol([onInit], Decl(component.ts, 6, 10))
>onInit : Symbol(onInit, Decl(component.ts, 0, 13))
}
const o = {
>o : Symbol(o, Decl(component.ts, 10, 5))
[onInit]: 0 // Error
>[onInit] : Symbol([onInit], Decl(component.ts, 10, 11))
>onInit : Symbol(onInit, Decl(component.ts, 0, 13))
};
class C {
>C : Symbol(C, Decl(component.ts, 12, 2))
[onInit]: any; // Error (because class fields)
>[onInit] : Symbol(C[onInit], Decl(component.ts, 14, 9))
>onInit : Symbol(onInit, Decl(component.ts, 0, 13))
}
class D {
>D : Symbol(D, Decl(component.ts, 16, 1))
[onInit] = 0; // Error
>[onInit] : Symbol(D[onInit], Decl(component.ts, 18, 9))
>onInit : Symbol(onInit, Decl(component.ts, 0, 13))
}
class E {
>E : Symbol(E, Decl(component.ts, 20, 1))
[onInit]() {} // Error
>[onInit] : Symbol(E[onInit], Decl(component.ts, 22, 9))
>onInit : Symbol(onInit, Decl(component.ts, 0, 13))
}
abstract class F {
>F : Symbol(F, Decl(component.ts, 24, 1))
abstract [onInit](): void;
>[onInit] : Symbol(F[onInit], Decl(component.ts, 26, 18))
>onInit : Symbol(onInit, Decl(component.ts, 0, 13))
}
class G {
>G : Symbol(G, Decl(component.ts, 28, 1))
declare [onInit]: any;
>[onInit] : Symbol(G[onInit], Decl(component.ts, 30, 9))
>onInit : Symbol(onInit, Decl(component.ts, 0, 13))
}
declare class H {
>H : Symbol(H, Decl(component.ts, 32, 1))
[onInit]: any;
>[onInit] : Symbol(H[onInit], Decl(component.ts, 34, 17))
>onInit : Symbol(onInit, Decl(component.ts, 0, 13))
}
@@ -0,0 +1,85 @@
=== tests/cases/conformance/externalModules/typeOnly/framework-hooks.ts ===
export const onInit = Symbol("onInit");
>onInit : unique symbol
>Symbol("onInit") : unique symbol
>Symbol : SymbolConstructor
>"onInit" : "onInit"
=== tests/cases/conformance/externalModules/typeOnly/component.ts ===
import type { onInit } from "./framework-hooks";
>onInit : any
interface Component {
[onInit]?(): void;
>[onInit] : () => void
>onInit : unique symbol
}
type T = {
>T : T
[onInit]: any;
>[onInit] : any
>onInit : unique symbol
}
const o = {
>o : { [onInit]: number; }
>{ [onInit]: 0 // Error} : { [onInit]: number; }
[onInit]: 0 // Error
>[onInit] : number
>onInit : unique symbol
>0 : 0
};
class C {
>C : C
[onInit]: any; // Error (because class fields)
>[onInit] : any
>onInit : unique symbol
}
class D {
>D : D
[onInit] = 0; // Error
>[onInit] : number
>onInit : unique symbol
>0 : 0
}
class E {
>E : E
[onInit]() {} // Error
>[onInit] : () => void
>onInit : unique symbol
}
abstract class F {
>F : F
abstract [onInit](): void;
>[onInit] : () => void
>onInit : unique symbol
}
class G {
>G : G
declare [onInit]: any;
>[onInit] : any
>onInit : unique symbol
}
declare class H {
>H : H
[onInit]: any;
>[onInit] : any
>onInit : unique symbol
}
+6 -4
View File
@@ -1,5 +1,5 @@
/b.ts(3,1): error TS1362: Enum 'SyntaxKind' cannot be used as a value because only its type has been imported.
/b.ts(4,1): error TS1362: Enum 'SymbolFlags' cannot be used as a value because only its type has been imported.
/b.ts(3,1): error TS1361: 'SyntaxKind' cannot be used as a value because it was imported using 'import type'.
/b.ts(4,1): error TS1361: 'SymbolFlags' cannot be used as a value because it was imported using 'import type'.
==== /a.ts (0 errors) ====
@@ -21,10 +21,12 @@
SyntaxKind.ImportClause;
~~~~~~~~~~
!!! error TS1362: Enum 'SyntaxKind' cannot be used as a value because only its type has been imported.
!!! error TS1361: 'SyntaxKind' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 /b.ts:1:15: 'SyntaxKind' was imported here.
SymbolFlags.Type;
~~~~~~~~~~~
!!! error TS1362: Enum 'SymbolFlags' cannot be used as a value because only its type has been imported.
!!! error TS1361: 'SymbolFlags' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 /b.ts:1:27: 'SymbolFlags' was imported here.
let kind: SyntaxKind.ImportClause;
let flags: SymbolFlags;
+1 -1
View File
@@ -43,7 +43,7 @@ var SyntaxKind;
"use strict";
exports.__esModule = true;
SyntaxKind.ImportClause;
SymbolFlags.Type;
"Type" /* Type */;
var kind;
var flags;
//// [c.js]
+10 -2
View File
@@ -31,11 +31,19 @@ import type { SyntaxKind, SymbolFlags } from './a';
>SymbolFlags : Symbol(SymbolFlags, Decl(b.ts, 0, 25))
SyntaxKind.ImportClause;
>SyntaxKind.ImportClause : Symbol(SyntaxKind.ImportClause, Decl(a.ts, 0, 17))
>SyntaxKind : Symbol(SyntaxKind, Decl(b.ts, 0, 13))
>ImportClause : Symbol(SyntaxKind.ImportClause, Decl(a.ts, 0, 17))
SymbolFlags.Type;
>SymbolFlags.Type : Symbol(SymbolFlags.Type, Decl(a.ts, 5, 24))
>SymbolFlags : Symbol(SymbolFlags, Decl(b.ts, 0, 25))
>Type : Symbol(SymbolFlags.Type, Decl(a.ts, 5, 24))
let kind: SyntaxKind.ImportClause;
>kind : Symbol(kind, Decl(b.ts, 4, 3))
>SyntaxKind : Symbol(SyntaxKind, Decl(b.ts, 0, 13))
>ImportClause : Symbol(SyntaxKind.ImportClause)
>ImportClause : Symbol(SyntaxKind.ImportClause, Decl(a.ts, 0, 17))
let flags: SymbolFlags;
>flags : Symbol(flags, Decl(b.ts, 5, 3))
@@ -44,7 +52,7 @@ let flags: SymbolFlags;
type TypeFlag = SymbolFlags.Type;
>TypeFlag : Symbol(TypeFlag, Decl(b.ts, 5, 23))
>SymbolFlags : Symbol(SymbolFlags, Decl(b.ts, 0, 25))
>Type : Symbol(SymbolFlags.Type)
>Type : Symbol(SymbolFlags.Type, Decl(a.ts, 5, 24))
export type { TypeFlag };
>TypeFlag : Symbol(TypeFlag, Decl(b.ts, 8, 13))
+10 -10
View File
@@ -30,31 +30,31 @@ export { SymbolFlags };
=== /b.ts ===
import type { SyntaxKind, SymbolFlags } from './a';
>SyntaxKind : SyntaxKind
>SymbolFlags : import("/a").SymbolFlags
>SymbolFlags : SymbolFlags
SyntaxKind.ImportClause;
>SyntaxKind.ImportClause : any
>SyntaxKind : any
>ImportClause : any
>SyntaxKind.ImportClause : SyntaxKind.ImportClause
>SyntaxKind : typeof SyntaxKind
>ImportClause : SyntaxKind.ImportClause
SymbolFlags.Type;
>SymbolFlags.Type : any
>SymbolFlags : any
>Type : any
>SymbolFlags.Type : SymbolFlags.Type
>SymbolFlags : typeof SymbolFlags
>Type : SymbolFlags.Type
let kind: SyntaxKind.ImportClause;
>kind : SyntaxKind.ImportClause
>SyntaxKind : any
let flags: SymbolFlags;
>flags : import("/a").SymbolFlags
>flags : SymbolFlags
type TypeFlag = SymbolFlags.Type;
>TypeFlag : import("/a").SymbolFlags.Type
>TypeFlag : SymbolFlags.Type
>SymbolFlags : any
export type { TypeFlag };
>TypeFlag : import("/a").SymbolFlags.Type
>TypeFlag : SymbolFlags.Type
=== /c.ts ===
import { SymbolFlags } from './a';
@@ -1,4 +1,4 @@
/b.ts(3,5): error TS2693: 'A' only refers to a type, but is being used as a value here.
/b.ts(3,5): error TS1362: 'A' cannot be used as a value because it was exported using 'export type'.
==== /a.ts (0 errors) ====
@@ -10,5 +10,6 @@
declare const a: A;
new A();
~
!!! error TS2693: 'A' only refers to a type, but is being used as a value here.
!!! error TS1362: 'A' cannot be used as a value because it was exported using 'export type'.
!!! related TS1377 /a.ts:2:15: 'A' was exported here.
@@ -14,4 +14,5 @@ declare const a: A;
>A : Symbol(A, Decl(b.ts, 0, 8))
new A();
>A : Symbol(A, Decl(b.ts, 0, 8))
@@ -7,12 +7,12 @@ export type { A };
=== /b.ts ===
import { A } from './a';
>A : any
>A : typeof A
declare const a: A;
>a : A
new A();
>new A() : any
>A : any
>new A() : A
>A : typeof A
@@ -1,4 +1,4 @@
/c.ts(3,5): error TS2693: 'A' only refers to a type, but is being used as a value here.
/c.ts(3,5): error TS1362: 'A' cannot be used as a value because it was exported using 'export type'.
==== /a.ts (0 errors) ====
@@ -12,5 +12,6 @@
declare const a: A;
new A();
~
!!! error TS2693: 'A' only refers to a type, but is being used as a value here.
!!! error TS1362: 'A' cannot be used as a value because it was exported using 'export type'.
!!! related TS1377 /b.ts:1:15: 'A' was exported here.
@@ -15,4 +15,5 @@ declare const a: A;
>A : Symbol(A, Decl(c.ts, 0, 8))
new A();
>A : Symbol(A, Decl(c.ts, 0, 8))
@@ -8,12 +8,12 @@ export type { A } from './a';
=== /c.ts ===
import { A } from './b';
>A : any
>A : typeof A
declare const a: A;
>a : import("/a").A
>a : A
new A();
>new A() : any
>A : any
>new A() : A
>A : typeof A
@@ -1,18 +0,0 @@
/a.ts(2,15): error TS1361: Type-only export must reference a type, but 'A' is a value.
/b.ts(1,15): error TS1361: Type-only export must reference a type, but 'AA' is a value.
==== /a.ts (1 errors) ====
const A = {};
export type { A };
~
!!! error TS1361: Type-only export must reference a type, but 'A' is a value.
!!! related TS2728 /a.ts:1:7: 'A' is declared here.
export const AA = {};
==== /b.ts (1 errors) ====
export type { AA } from './a';
~~
!!! error TS1361: Type-only export must reference a type, but 'AA' is a value.
!!! related TS2728 /a.ts:3:14: 'AA' is declared here.
@@ -1,5 +1,5 @@
/a.ts(2,1): error TS2708: Cannot use namespace 'ns' as a value.
/a.ts(3,1): error TS2708: Cannot use namespace 'ns' as a value.
/a.ts(2,1): error TS1361: 'ns' cannot be used as a value because it was imported using 'import type'.
/a.ts(3,1): error TS1361: 'ns' cannot be used as a value because it was imported using 'import type'.
==== /ns.ts (0 errors) ====
@@ -20,10 +20,12 @@
import type ns from './ns';
ns.Class; // Error
~~
!!! error TS2708: Cannot use namespace 'ns' as a value.
!!! error TS1361: 'ns' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 /a.ts:1:8: 'ns' was imported here.
ns.Value; // Error
~~
!!! error TS2708: Cannot use namespace 'ns' as a value.
!!! error TS1361: 'ns' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 /a.ts:1:8: 'ns' was imported here.
let c: ns.Class;
let t: ns.Type = "";
let n: ns.nested.NestedClass = { a: '' };
@@ -31,11 +31,19 @@ import type ns from './ns';
>ns : Symbol(ns, Decl(a.ts, 0, 6))
ns.Class; // Error
>ns.Class : Symbol(ns.Class, Decl(ns.ts, 1, 28))
>ns : Symbol(ns, Decl(a.ts, 0, 6))
>Class : Symbol(ns.Class, Decl(ns.ts, 1, 28))
ns.Value; // Error
>ns.Value : Symbol(ns.Value, Decl(ns.ts, 3, 14))
>ns : Symbol(ns, Decl(a.ts, 0, 6))
>Value : Symbol(ns.Value, Decl(ns.ts, 3, 14))
let c: ns.Class;
>c : Symbol(c, Decl(a.ts, 3, 3))
>ns : Symbol(ns, Decl(a.ts, 0, 6))
>Class : Symbol(ns.Class)
>Class : Symbol(ns.Class, Decl(ns.ts, 1, 28))
let t: ns.Type = "";
>t : Symbol(t, Decl(a.ts, 4, 3))
@@ -46,6 +54,6 @@ let n: ns.nested.NestedClass = { a: '' };
>n : Symbol(n, Decl(a.ts, 5, 3))
>ns : Symbol(ns, Decl(a.ts, 0, 6))
>nested : Symbol(ns.nested, Decl(ns.ts, 3, 26))
>NestedClass : Symbol(NestedClass)
>NestedClass : Symbol(ns.nested.NestedClass, Decl(ns.ts, 4, 27))
>a : Symbol(a, Decl(a.ts, 5, 32))
@@ -32,17 +32,17 @@ import type ns from './ns';
>ns : any
ns.Class; // Error
>ns.Class : any
>ns : any
>Class : any
>ns.Class : typeof ns.Class
>ns : typeof ns
>Class : typeof ns.Class
ns.Value; // Error
>ns.Value : any
>ns : any
>Value : any
>ns.Value : ""
>ns : typeof ns
>Value : ""
let c: ns.Class;
>c : import("/ns").default.Class
>c : ns.Class
>ns : any
let t: ns.Type = "";
@@ -51,7 +51,7 @@ let t: ns.Type = "";
>"" : ""
let n: ns.nested.NestedClass = { a: '' };
>n : import("/ns").default.nested.NestedClass
>n : ns.nested.NestedClass
>ns : any
>nested : any
>{ a: '' } : { a: string; }
+1 -1
View File
@@ -6,7 +6,7 @@ export class A<T> { a!: T }
>T : Symbol(T, Decl(a.ts, 0, 15))
export type { A as B };
>A : Symbol(A)
>A : Symbol(A, Decl(a.ts, 0, 0))
>B : Symbol(B, Decl(a.ts, 1, 13))
=== /b.ts ===
+6 -6
View File
@@ -4,30 +4,30 @@ export class A<T> { a!: T }
>a : T
export type { A as B };
>A : A<T>
>A : typeof A
>B : A<T>
=== /b.ts ===
import type { A } from './a';
>A : import("/a").A<T>
>A : A<T>
import { B } from './a';
>B : any
>B : typeof A
let a: A<string> = { a: "" };
>a : import("/a").A<string>
>a : A<string>
>{ a: "" } : { a: string; }
>a : string
>"" : ""
let b: B<number> = { a: 3 };
>b : import("/a").A<number>
>b : A<number>
>{ a: 3 } : { a: number; }
>a : number
>3 : 3
let c: A<boolean> = {};
>c : import("/a").A<boolean>
>c : A<boolean>
>{} : {}
let d: B = { a: "" };
@@ -1,4 +1,4 @@
/b.ts(2,5): error TS2693: 'A' only refers to a type, but is being used as a value here.
/b.ts(2,5): error TS1361: 'A' cannot be used as a value because it was imported using 'import type'.
==== /a.ts (0 errors) ====
@@ -8,6 +8,7 @@
import type A from './a';
new A();
~
!!! error TS2693: 'A' only refers to a type, but is being used as a value here.
!!! error TS1361: 'A' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 /b.ts:1:8: 'A' was imported here.
let a: A = { a: '' };
@@ -8,6 +8,8 @@ import type A from './a';
>A : Symbol(A, Decl(b.ts, 0, 6))
new A();
>A : Symbol(A, Decl(b.ts, 0, 6))
let a: A = { a: '' };
>a : Symbol(a, Decl(b.ts, 2, 3))
>A : Symbol(A, Decl(b.ts, 0, 6))
@@ -5,14 +5,14 @@ export default class A { a!: string }
=== /b.ts ===
import type A from './a';
>A : import("/a").default
>A : A
new A();
>new A() : any
>A : any
>new A() : A
>A : typeof A
let a: A = { a: '' };
>a : import("/a").default
>a : A
>{ a: '' } : { a: string; }
>a : string
>'' : ""
@@ -1,5 +1,4 @@
/d.ts(1,21): error TS1361: Type-only import must reference a type, but 'C' is a value.
/d.ts(2,5): error TS2693: 'A' only refers to a type, but is being used as a value here.
/d.ts(2,5): error TS1361: 'A' cannot be used as a value because it was imported using 'import type'.
==== /abc.ts (0 errors) ====
@@ -7,14 +6,12 @@
export type B = { b: string };
export const C = "";
==== /d.ts (2 errors) ====
==== /d.ts (1 errors) ====
import type { A, B, C } from './abc';
~
!!! error TS1361: Type-only import must reference a type, but 'C' is a value.
!!! related TS2728 /abc.ts:3:14: 'C' is declared here.
new A();
~
!!! error TS2693: 'A' only refers to a type, but is being used as a value here.
!!! error TS1361: 'A' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 /d.ts:1:15: 'A' was imported here.
declare let a: A;
declare let b: B;
b.b;
@@ -16,6 +16,8 @@ import type { A, B, C } from './abc';
>C : Symbol(C, Decl(d.ts, 0, 19))
new A();
>A : Symbol(A, Decl(d.ts, 0, 13))
declare let a: A;
>a : Symbol(a, Decl(d.ts, 2, 11))
>A : Symbol(A, Decl(d.ts, 0, 13))
@@ -12,16 +12,16 @@ export const C = "";
=== /d.ts ===
import type { A, B, C } from './abc';
>A : import("/abc").A
>A : A
>B : B
>C : any
new A();
>new A() : any
>A : any
>new A() : A
>A : typeof A
declare let a: A;
>a : import("/abc").A
>a : A
declare let b: B;
>b : B
@@ -1,5 +1,5 @@
/b.ts(2,1): error TS2708: Cannot use namespace 'types' as a value.
/b.ts(3,1): error TS2708: Cannot use namespace 'types' as a value.
/b.ts(2,1): error TS1361: 'types' cannot be used as a value because it was imported using 'import type'.
/b.ts(3,1): error TS1361: 'types' cannot be used as a value because it was imported using 'import type'.
/b.ts(4,14): error TS2694: Namespace '"/a"' has no exported member 'Value'.
/b.ts(5,7): error TS2741: Property 'a' is missing in type '{}' but required in type 'A'.
/b.ts(6,7): error TS2741: Property 'b' is missing in type '{}' but required in type 'B'.
@@ -15,10 +15,12 @@
import type * as types from './a';
types;
~~~~~
!!! error TS2708: Cannot use namespace 'types' as a value.
!!! error TS1361: 'types' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 /b.ts:1:13: 'types' was imported here.
types.Value;
~~~~~
!!! error TS2708: Cannot use namespace 'types' as a value.
!!! error TS1361: 'types' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 /b.ts:1:13: 'types' was imported here.
let v: types.Value;
~~~~~
!!! error TS2694: Namespace '"/a"' has no exported member 'Value'.
@@ -20,7 +20,13 @@ import type * as types from './a';
>types : Symbol(types, Decl(b.ts, 0, 11))
types;
>types : Symbol(types, Decl(b.ts, 0, 11))
types.Value;
>types.Value : Symbol(types.Value, Decl(a.ts, 3, 12))
>types : Symbol(types, Decl(b.ts, 0, 11))
>Value : Symbol(types.Value, Decl(a.ts, 3, 12))
let v: types.Value;
>v : Symbol(v, Decl(b.ts, 3, 3))
>types : Symbol(types, Decl(b.ts, 0, 11))
@@ -28,12 +34,12 @@ let v: types.Value;
const a: types.A = {};
>a : Symbol(a, Decl(b.ts, 4, 5))
>types : Symbol(types, Decl(b.ts, 0, 11))
>A : Symbol(types.A)
>A : Symbol(types.A, Decl(a.ts, 0, 0))
const b: types.B = {};
>b : Symbol(b, Decl(b.ts, 5, 5))
>types : Symbol(types, Decl(b.ts, 0, 11))
>B : Symbol(types.B)
>B : Symbol(types.B, Decl(a.ts, 0, 29))
const c: types.C<string> = "";
>c : Symbol(c, Decl(b.ts, 6, 5))
@@ -16,27 +16,27 @@ export const Value = {};
=== /b.ts ===
import type * as types from './a';
>types : any
>types : typeof types
types;
>types : any
>types : typeof types
types.Value;
>types.Value : any
>types : any
>Value : any
>types.Value : {}
>types : typeof types
>Value : {}
let v: types.Value;
>v : any
>types : any
const a: types.A = {};
>a : import("/a").A
>a : types.A
>types : any
>{} : {}
const b: types.B = {};
>b : import("/a").B
>b : types.B
>types : any
>{} : {}
@@ -1,12 +1,14 @@
/b.ts(1,1): error TS1371: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
/c.ts(1,1): error TS1371: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
/e.ts(1,1): error TS6192: All imports in import declaration are unused.
/g.ts(1,1): error TS1371: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
==== /a.ts (0 errors) ====
export default class {}
export class A {}
export type B = {};
export const enum C { One, Two }
==== /b.ts (1 errors) ====
import { A, B } from './a'; // Error
@@ -34,4 +36,19 @@
import { A, B } from './a'; // noUnusedLocals error only
~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS6192: All imports in import declaration are unused.
==== /f.ts (0 errors) ====
import { C } from './a';
import type { C as D } from './a';
C.One;
let c: D = C.Two;
let d: D.Two = C.Two;
console.log(c, d);
==== /g.ts (1 errors) ====
import { C } from './a';
~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1371: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
let c: C;
let d: C.Two;
console.log(c, d);
@@ -4,6 +4,7 @@
export default class {}
export class A {}
export type B = {};
export const enum C { One, Two }
//// [b.ts]
import { A, B } from './a'; // Error
@@ -26,6 +27,19 @@ console.log(a, b);
//// [e.ts]
import { A, B } from './a'; // noUnusedLocals error only
//// [f.ts]
import { C } from './a';
import type { C as D } from './a';
C.One;
let c: D = C.Two;
let d: D.Two = C.Two;
console.log(c, d);
//// [g.ts]
import { C } from './a';
let c: C;
let d: C.Two;
console.log(c, d);
//// [a.js]
"use strict";
@@ -67,3 +81,18 @@ console.log(a, b);
"use strict";
exports.__esModule = true;
require("./a"); // noUnusedLocals error only
//// [f.js]
"use strict";
exports.__esModule = true;
require("./a");
0 /* One */;
var c = 1 /* Two */;
var d = 1 /* Two */;
console.log(c, d);
//// [g.js]
"use strict";
exports.__esModule = true;
require("./a");
var c;
var d;
console.log(c, d);
@@ -6,6 +6,11 @@ export class A {}
export type B = {};
>B : Symbol(B, Decl(a.ts, 1, 17))
export const enum C { One, Two }
>C : Symbol(C, Decl(a.ts, 2, 19))
>One : Symbol(C.One, Decl(a.ts, 3, 21))
>Two : Symbol(C.Two, Decl(a.ts, 3, 26))
=== /b.ts ===
import { A, B } from './a'; // Error
>A : Symbol(A, Decl(b.ts, 0, 8))
@@ -72,3 +77,58 @@ import { A, B } from './a'; // noUnusedLocals error only
>A : Symbol(A, Decl(e.ts, 0, 8))
>B : Symbol(B, Decl(e.ts, 0, 11))
=== /f.ts ===
import { C } from './a';
>C : Symbol(C, Decl(f.ts, 0, 8))
import type { C as D } from './a';
>C : Symbol(C, Decl(a.ts, 2, 19))
>D : Symbol(D, Decl(f.ts, 1, 13))
C.One;
>C.One : Symbol(C.One, Decl(a.ts, 3, 21))
>C : Symbol(C, Decl(f.ts, 0, 8))
>One : Symbol(C.One, Decl(a.ts, 3, 21))
let c: D = C.Two;
>c : Symbol(c, Decl(f.ts, 3, 3))
>D : Symbol(D, Decl(f.ts, 1, 13))
>C.Two : Symbol(C.Two, Decl(a.ts, 3, 26))
>C : Symbol(C, Decl(f.ts, 0, 8))
>Two : Symbol(C.Two, Decl(a.ts, 3, 26))
let d: D.Two = C.Two;
>d : Symbol(d, Decl(f.ts, 4, 3))
>D : Symbol(D, Decl(f.ts, 1, 13))
>Two : Symbol(C.Two, Decl(a.ts, 3, 26))
>C.Two : Symbol(C.Two, Decl(a.ts, 3, 26))
>C : Symbol(C, Decl(f.ts, 0, 8))
>Two : Symbol(C.Two, Decl(a.ts, 3, 26))
console.log(c, d);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>c : Symbol(c, Decl(f.ts, 3, 3))
>d : Symbol(d, Decl(f.ts, 4, 3))
=== /g.ts ===
import { C } from './a';
>C : Symbol(C, Decl(g.ts, 0, 8))
let c: C;
>c : Symbol(c, Decl(g.ts, 1, 3))
>C : Symbol(C, Decl(g.ts, 0, 8))
let d: C.Two;
>d : Symbol(d, Decl(g.ts, 2, 3))
>C : Symbol(C, Decl(g.ts, 0, 8))
>Two : Symbol(C.Two, Decl(a.ts, 3, 26))
console.log(c, d);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>c : Symbol(c, Decl(g.ts, 1, 3))
>d : Symbol(d, Decl(g.ts, 2, 3))
@@ -6,6 +6,11 @@ export class A {}
export type B = {};
>B : B
export const enum C { One, Two }
>C : C
>One : C.One
>Two : C.Two
=== /b.ts ===
import { A, B } from './a'; // Error
>A : typeof A
@@ -70,3 +75,56 @@ import { A, B } from './a'; // noUnusedLocals error only
>A : typeof A
>B : any
=== /f.ts ===
import { C } from './a';
>C : typeof C
import type { C as D } from './a';
>C : typeof C
>D : C
C.One;
>C.One : C.One
>C : typeof C
>One : C.One
let c: D = C.Two;
>c : C
>C.Two : C.Two
>C : typeof C
>Two : C.Two
let d: D.Two = C.Two;
>d : C.Two
>D : any
>C.Two : C.Two
>C : typeof C
>Two : C.Two
console.log(c, d);
>console.log(c, d) : void
>console.log : (message?: any, ...optionalParams: any[]) => void
>console : Console
>log : (message?: any, ...optionalParams: any[]) => void
>c : C.Two
>d : C.Two
=== /g.ts ===
import { C } from './a';
>C : typeof C
let c: C;
>c : C
let d: C.Two;
>d : C.Two
>C : any
console.log(c, d);
>console.log(c, d) : void
>console.log : (message?: any, ...optionalParams: any[]) => void
>console : Console
>log : (message?: any, ...optionalParams: any[]) => void
>c : C
>d : C.Two
@@ -0,0 +1,15 @@
/b.ts(2,21): error TS2339: Property 'A' does not exist on type 'typeof import("/a")'.
==== /a.ts (0 errors) ====
class A {}
export type { A };
export class B {};
==== /b.ts (1 errors) ====
import * as types from './a';
let A: typeof types.A;
~
!!! error TS2339: Property 'A' does not exist on type 'typeof import("/a")'.
let B: typeof types.B;
@@ -0,0 +1,33 @@
//// [tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery.ts] ////
//// [a.ts]
class A {}
export type { A };
export class B {};
//// [b.ts]
import * as types from './a';
let A: typeof types.A;
let B: typeof types.B;
//// [a.js]
"use strict";
exports.__esModule = true;
var A = /** @class */ (function () {
function A() {
}
return A;
}());
var B = /** @class */ (function () {
function B() {
}
return B;
}());
exports.B = B;
;
//// [b.js]
"use strict";
exports.__esModule = true;
var A;
var B;
@@ -0,0 +1,24 @@
=== /a.ts ===
class A {}
>A : Symbol(A, Decl(a.ts, 0, 0))
export type { A };
>A : Symbol(A, Decl(a.ts, 1, 13))
export class B {};
>B : Symbol(B, Decl(a.ts, 1, 18))
=== /b.ts ===
import * as types from './a';
>types : Symbol(types, Decl(b.ts, 0, 6))
let A: typeof types.A;
>A : Symbol(A, Decl(b.ts, 1, 3))
>types : Symbol(types, Decl(b.ts, 0, 6))
let B: typeof types.B;
>B : Symbol(B, Decl(b.ts, 2, 3))
>types.B : Symbol(types.B, Decl(a.ts, 1, 18))
>types : Symbol(types, Decl(b.ts, 0, 6))
>B : Symbol(types.B, Decl(a.ts, 1, 18))
@@ -0,0 +1,26 @@
=== /a.ts ===
class A {}
>A : A
export type { A };
>A : A
export class B {};
>B : B
=== /b.ts ===
import * as types from './a';
>types : typeof types
let A: typeof types.A;
>A : any
>types.A : any
>types : typeof types
>A : any
let B: typeof types.B;
>B : typeof types.B
>types.B : typeof types.B
>types : typeof types
>B : typeof types.B
@@ -0,0 +1,16 @@
/b.ts(2,7): error TS2339: Property 'A' does not exist on type 'typeof import("/a")'.
/b.ts(3,9): error TS2339: Property 'A' does not exist on type 'typeof import("/a")'.
==== /a.ts (0 errors) ====
class A { a!: string }
export type { A };
==== /b.ts (2 errors) ====
import * as types from './a';
types.A;
~
!!! error TS2339: Property 'A' does not exist on type 'typeof import("/a")'.
const { A } = types;
~
!!! error TS2339: Property 'A' does not exist on type 'typeof import("/a")'.
@@ -0,0 +1,25 @@
//// [tests/cases/conformance/externalModules/typeOnly/namespaceMemberAccess.ts] ////
//// [a.ts]
class A { a!: string }
export type { A };
//// [b.ts]
import * as types from './a';
types.A;
const { A } = types;
//// [a.js]
"use strict";
exports.__esModule = true;
var A = /** @class */ (function () {
function A() {
}
return A;
}());
//// [b.js]
"use strict";
exports.__esModule = true;
var types = require("./a");
types.A;
var A = types.A;
@@ -0,0 +1,19 @@
=== /a.ts ===
class A { a!: string }
>A : Symbol(A, Decl(a.ts, 0, 0))
>a : Symbol(A.a, Decl(a.ts, 0, 9))
export type { A };
>A : Symbol(A, Decl(a.ts, 1, 13))
=== /b.ts ===
import * as types from './a';
>types : Symbol(types, Decl(b.ts, 0, 6))
types.A;
>types : Symbol(types, Decl(b.ts, 0, 6))
const { A } = types;
>A : Symbol(A, Decl(b.ts, 2, 7))
>types : Symbol(types, Decl(b.ts, 0, 6))
@@ -0,0 +1,21 @@
=== /a.ts ===
class A { a!: string }
>A : A
>a : string
export type { A };
>A : A
=== /b.ts ===
import * as types from './a';
>types : typeof types
types.A;
>types.A : any
>types : typeof types
>A : any
const { A } = types;
>A : any
>types : typeof types
+1 -1
View File
@@ -4,7 +4,7 @@ class A { a!: string }
>a : Symbol(A.a, Decl(a.ts, 0, 9))
export type { A as B };
>A : Symbol(A)
>A : Symbol(A, Decl(a.ts, 0, 0))
>B : Symbol(B, Decl(a.ts, 1, 13))
=== /b.ts ===
+6 -6
View File
@@ -4,20 +4,20 @@ class A { a!: string }
>a : string
export type { A as B };
>A : A
>A : typeof A
>B : A
=== /b.ts ===
export type { B as C } from './a';
>B : A
>C : A
>B : typeof import("/a").B
>C : import("/a").B
=== /c.ts ===
import type { C as D } from './b';
>C : A
>D : A
>C : typeof D
>D : D
const d: D = {};
>d : A
>d : D
>{} : {}
@@ -1,9 +1,9 @@
tests/cases/conformance/externalModules/topLevelAwait.ts(2,1): error TS1376: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.
tests/cases/conformance/externalModules/topLevelAwait.ts(2,1): error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.
==== tests/cases/conformance/externalModules/topLevelAwait.ts (1 errors) ====
export const x = 1;
await x;
~~~~~
!!! error TS1376: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.
!!! error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.
@@ -1,9 +1,9 @@
tests/cases/conformance/externalModules/topLevelAwait.ts(2,1): error TS1376: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.
tests/cases/conformance/externalModules/topLevelAwait.ts(2,1): error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.
==== tests/cases/conformance/externalModules/topLevelAwait.ts (1 errors) ====
export const x = 1;
await x;
~~~~~
!!! error TS1376: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.
!!! error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.
+23
View File
@@ -0,0 +1,23 @@
//// [tests/cases/conformance/externalModules/typeOnly/typeQuery.ts] ////
//// [a.ts]
export class A { }
//// [b.ts]
import type { A } from './a';
let AConstructor: typeof A;
//// [a.js]
"use strict";
exports.__esModule = true;
var A = /** @class */ (function () {
function A() {
}
return A;
}());
exports.A = A;
//// [b.js]
"use strict";
exports.__esModule = true;
var AConstructor;
@@ -0,0 +1,12 @@
=== /a.ts ===
export class A { }
>A : Symbol(A, Decl(a.ts, 0, 0))
=== /b.ts ===
import type { A } from './a';
>A : Symbol(A, Decl(b.ts, 0, 13))
let AConstructor: typeof A;
>AConstructor : Symbol(AConstructor, Decl(b.ts, 1, 3))
>A : Symbol(A, Decl(b.ts, 0, 13))
+12
View File
@@ -0,0 +1,12 @@
=== /a.ts ===
export class A { }
>A : A
=== /b.ts ===
import type { A } from './a';
>A : A
let AConstructor: typeof A;
>AConstructor : typeof A
>A : typeof A
@@ -0,0 +1,9 @@
// @Filename: /a.ts
export class A { a!: string }
// @Filename: /b.ts
import type { A } from './a';
declare class B extends A {}
declare namespace ns {
class C extends A {}
}
@@ -0,0 +1,19 @@
// @Filename: /a.ts
class A { a!: string }
export type { A as default };
// @Filename: /b.ts
import A from './a';
import type { default as B } from './a';
export { A, B };
// @Filename: /c.ts
import * as types from './b';
export { types as default };
// @Filename: /d.ts
import types from './c';
new types.A();
new types.B();
const a: types.A = {};
const b: types.B = {};
@@ -0,0 +1,43 @@
// @target: esnext
// @Filename: framework-hooks.ts
export const onInit = Symbol("onInit");
// @Filename: component.ts
import type { onInit } from "./framework-hooks";
interface Component {
[onInit]?(): void;
}
type T = {
[onInit]: any;
}
const o = {
[onInit]: 0 // Error
};
class C {
[onInit]: any; // Error (because class fields)
}
class D {
[onInit] = 0; // Error
}
class E {
[onInit]() {} // Error
}
abstract class F {
abstract [onInit](): void;
}
class G {
declare [onInit]: any;
}
declare class H {
[onInit]: any;
}
@@ -5,6 +5,7 @@
export default class {}
export class A {}
export type B = {};
export const enum C { One, Two }
// @Filename: /b.ts
import { A, B } from './a'; // Error
@@ -26,3 +27,17 @@ console.log(a, b);
// @Filename: /e.ts
import { A, B } from './a'; // noUnusedLocals error only
// @Filename: /f.ts
import { C } from './a';
import type { C as D } from './a';
C.One;
let c: D = C.Two;
let d: D.Two = C.Two;
console.log(c, d);
// @Filename: /g.ts
import { C } from './a';
let c: C;
let d: C.Two;
console.log(c, d);
@@ -0,0 +1,9 @@
// @Filename: /a.ts
class A {}
export type { A };
export class B {};
// @Filename: /b.ts
import * as types from './a';
let A: typeof types.A;
let B: typeof types.B;
@@ -0,0 +1,8 @@
// @Filename: /a.ts
class A { a!: string }
export type { A };
// @Filename: /b.ts
import * as types from './a';
types.A;
const { A } = types;
@@ -0,0 +1,6 @@
// @Filename: /a.ts
export class A { }
// @Filename: /b.ts
import type { A } from './a';
let AConstructor: typeof A;