diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 92ba8cb9fb56a..508d2dd135a40 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1861,10 +1861,36 @@ namespace ts { error(errorLocation, Diagnostics.Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it, declarationNameToString(associatedDeclarationForContainingInitializer.name), declarationNameToString(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 { @@ -8286,20 +8267,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); @@ -11030,9 +11001,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); } @@ -20289,8 +20257,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); + } } } @@ -22849,7 +22822,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); } } @@ -29656,7 +29629,8 @@ namespace ts { if (rootSymbol && rootSymbol.flags & SymbolFlags.Alias && symbolIsValue(rootSymbol) - && !isConstEnumOrConstEnumOnlyModule(resolveAlias(rootSymbol))) { + && !isConstEnumOrConstEnumOnlyModule(resolveAlias(rootSymbol)) + && !getTypeOnlyAliasDeclaration(rootSymbol)) { markAliasSymbolAsReferenced(rootSymbol); } } @@ -33111,17 +33085,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) { @@ -33131,15 +33103,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); } } } @@ -33636,7 +33605,10 @@ namespace ts { }); } - if (!node.isDeclarationFile && isExternalModule(node)) { + if (compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Error && + !node.isDeclarationFile && + isExternalModule(node) + ) { checkImportsForTypeOnlyConversion(node); } @@ -34227,7 +34199,7 @@ namespace ts { if (isDeclarationNameOrImportPropertyName(node)) { const symbol = getSymbolAtLocation(node); if (symbol) { - return isTypeOnlyImportOrExportName(node) ? getDeclaredTypeOfSymbol(symbol) : getTypeOfSymbol(symbol); + return getTypeOfSymbol(symbol); } return errorType; } @@ -34468,7 +34440,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); } } @@ -34558,11 +34530,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 = (node).exportClause; return !!exportClause && ( @@ -34611,7 +34585,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; } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 2eb261499d50f..e5bd3aa13996f 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -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, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index b4d6bea4fcae8..b71e9fef7dd99 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -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", diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index bcab043fd25e5..9d7dc9375996b 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -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( diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 1009e75fa89c8..71ae7d27c8e22 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -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; // Instantiations of generic type alias (undefined if non-generic) inferredClassSymbol?: Map; // 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 diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 76394eeef538a..e71fac157627c 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -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 { - 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 && (node).moduleReference.kind === SyntaxKind.ExternalModuleReference; } @@ -2285,6 +2298,19 @@ namespace ts { return node.kind === SyntaxKind.ImportDeclaration && !!node.importClause && !!node.importClause.name; } + export function forEachImportClauseDeclaration(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); } diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index d4bc403b85908..cc36af32f2c77 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -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; } diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 1aa1160a6a60b..a51c159f29763 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -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[] = []; diff --git a/tests/baselines/reference/ambient.js b/tests/baselines/reference/ambient.js new file mode 100644 index 0000000000000..09f24592fcf0f --- /dev/null +++ b/tests/baselines/reference/ambient.js @@ -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; diff --git a/tests/baselines/reference/ambient.symbols b/tests/baselines/reference/ambient.symbols new file mode 100644 index 0000000000000..ce7d34b405286 --- /dev/null +++ b/tests/baselines/reference/ambient.symbols @@ -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)) +} + diff --git a/tests/baselines/reference/ambient.types b/tests/baselines/reference/ambient.types new file mode 100644 index 0000000000000..8f6695e7482b1 --- /dev/null +++ b/tests/baselines/reference/ambient.types @@ -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 +} + diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 1855fae39b672..a4e6820180669 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -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; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 1143d4c6ebceb..15ec1d721702a 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -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; diff --git a/tests/baselines/reference/awaitInNonAsyncFunction.errors.txt b/tests/baselines/reference/awaitInNonAsyncFunction.errors.txt index 8224911c3c63d..78eba138d0d14 100644 --- a/tests/baselines/reference/awaitInNonAsyncFunction.errors.txt +++ b/tests/baselines/reference/awaitInNonAsyncFunction.errors.txt @@ -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. \ No newline at end of file +!!! 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. \ No newline at end of file diff --git a/tests/baselines/reference/chained.errors.txt b/tests/baselines/reference/chained.errors.txt index 8d684afbb9475..d0e6f2c26f2fa 100644 --- a/tests/baselines/reference/chained.errors.txt +++ b/tests/baselines/reference/chained.errors.txt @@ -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'. diff --git a/tests/baselines/reference/chained.symbols b/tests/baselines/reference/chained.symbols index 9ba6d5bed2142..228befe74f543 100644 --- a/tests/baselines/reference/chained.symbols +++ b/tests/baselines/reference/chained.symbols @@ -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)) diff --git a/tests/baselines/reference/chained.types b/tests/baselines/reference/chained.types index 5e52f608b821b..c694bceffd5e1 100644 --- a/tests/baselines/reference/chained.types +++ b/tests/baselines/reference/chained.types @@ -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 >{} : {} diff --git a/tests/baselines/reference/chained2.errors.txt b/tests/baselines/reference/chained2.errors.txt new file mode 100644 index 0000000000000..64f61624db8e8 --- /dev/null +++ b/tests/baselines/reference/chained2.errors.txt @@ -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. + \ No newline at end of file diff --git a/tests/baselines/reference/chained2.js b/tests/baselines/reference/chained2.js new file mode 100644 index 0000000000000..4eea4824fdd09 --- /dev/null +++ b/tests/baselines/reference/chained2.js @@ -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 = {}; diff --git a/tests/baselines/reference/chained2.symbols b/tests/baselines/reference/chained2.symbols new file mode 100644 index 0000000000000..d4cf1c245ae8d --- /dev/null +++ b/tests/baselines/reference/chained2.symbols @@ -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)) + diff --git a/tests/baselines/reference/chained2.types b/tests/baselines/reference/chained2.types new file mode 100644 index 0000000000000..d3b12f0f25c8f --- /dev/null +++ b/tests/baselines/reference/chained2.types @@ -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 +>{} : {} + diff --git a/tests/baselines/reference/computedPropertyName.errors.txt b/tests/baselines/reference/computedPropertyName.errors.txt new file mode 100644 index 0000000000000..5038e0be48422 --- /dev/null +++ b/tests/baselines/reference/computedPropertyName.errors.txt @@ -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; + } + \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyName.js b/tests/baselines/reference/computedPropertyName.js new file mode 100644 index 0000000000000..a3378327f282d --- /dev/null +++ b/tests/baselines/reference/computedPropertyName.js @@ -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 { +} diff --git a/tests/baselines/reference/computedPropertyName.symbols b/tests/baselines/reference/computedPropertyName.symbols new file mode 100644 index 0000000000000..9a8e912fae160 --- /dev/null +++ b/tests/baselines/reference/computedPropertyName.symbols @@ -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)) +} + diff --git a/tests/baselines/reference/computedPropertyName.types b/tests/baselines/reference/computedPropertyName.types new file mode 100644 index 0000000000000..caab943f248ec --- /dev/null +++ b/tests/baselines/reference/computedPropertyName.types @@ -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 +} + diff --git a/tests/baselines/reference/enums.errors.txt b/tests/baselines/reference/enums.errors.txt index 4e874cbee48dc..8644a4dd172e2 100644 --- a/tests/baselines/reference/enums.errors.txt +++ b/tests/baselines/reference/enums.errors.txt @@ -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; diff --git a/tests/baselines/reference/enums.js b/tests/baselines/reference/enums.js index 09243e4a7f134..e71675f8c9c51 100644 --- a/tests/baselines/reference/enums.js +++ b/tests/baselines/reference/enums.js @@ -43,7 +43,7 @@ var SyntaxKind; "use strict"; exports.__esModule = true; SyntaxKind.ImportClause; -SymbolFlags.Type; +"Type" /* Type */; var kind; var flags; //// [c.js] diff --git a/tests/baselines/reference/enums.symbols b/tests/baselines/reference/enums.symbols index edac3617acbee..65e656707ee08 100644 --- a/tests/baselines/reference/enums.symbols +++ b/tests/baselines/reference/enums.symbols @@ -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)) diff --git a/tests/baselines/reference/enums.types b/tests/baselines/reference/enums.types index ca79cc6147d4a..943e039b26ce0 100644 --- a/tests/baselines/reference/enums.types +++ b/tests/baselines/reference/enums.types @@ -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'; diff --git a/tests/baselines/reference/exportDeclaration.errors.txt b/tests/baselines/reference/exportDeclaration.errors.txt index 387b348843945..6dbd0e8d9c421 100644 --- a/tests/baselines/reference/exportDeclaration.errors.txt +++ b/tests/baselines/reference/exportDeclaration.errors.txt @@ -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. \ No newline at end of file diff --git a/tests/baselines/reference/exportDeclaration.symbols b/tests/baselines/reference/exportDeclaration.symbols index c35f92e71592e..39b0f4755dfda 100644 --- a/tests/baselines/reference/exportDeclaration.symbols +++ b/tests/baselines/reference/exportDeclaration.symbols @@ -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)) diff --git a/tests/baselines/reference/exportDeclaration.types b/tests/baselines/reference/exportDeclaration.types index 277082b8586a8..69c1aab7dd9a5 100644 --- a/tests/baselines/reference/exportDeclaration.types +++ b/tests/baselines/reference/exportDeclaration.types @@ -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 diff --git a/tests/baselines/reference/exportDeclaration_moduleSpecifier.errors.txt b/tests/baselines/reference/exportDeclaration_moduleSpecifier.errors.txt index 6ef18aad95986..39cb01ddec045 100644 --- a/tests/baselines/reference/exportDeclaration_moduleSpecifier.errors.txt +++ b/tests/baselines/reference/exportDeclaration_moduleSpecifier.errors.txt @@ -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. \ No newline at end of file diff --git a/tests/baselines/reference/exportDeclaration_moduleSpecifier.symbols b/tests/baselines/reference/exportDeclaration_moduleSpecifier.symbols index e4917cddc066d..b24d2e93c0a4f 100644 --- a/tests/baselines/reference/exportDeclaration_moduleSpecifier.symbols +++ b/tests/baselines/reference/exportDeclaration_moduleSpecifier.symbols @@ -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)) diff --git a/tests/baselines/reference/exportDeclaration_moduleSpecifier.types b/tests/baselines/reference/exportDeclaration_moduleSpecifier.types index b870b2804f582..bc3feebdd9fbe 100644 --- a/tests/baselines/reference/exportDeclaration_moduleSpecifier.types +++ b/tests/baselines/reference/exportDeclaration_moduleSpecifier.types @@ -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 diff --git a/tests/baselines/reference/exportDeclaration_value.errors.txt b/tests/baselines/reference/exportDeclaration_value.errors.txt deleted file mode 100644 index d759ad8c7c57b..0000000000000 --- a/tests/baselines/reference/exportDeclaration_value.errors.txt +++ /dev/null @@ -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. - \ No newline at end of file diff --git a/tests/baselines/reference/filterNamespace_import.errors.txt b/tests/baselines/reference/filterNamespace_import.errors.txt index b9e9a09f8c790..916504c4879cd 100644 --- a/tests/baselines/reference/filterNamespace_import.errors.txt +++ b/tests/baselines/reference/filterNamespace_import.errors.txt @@ -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: '' }; diff --git a/tests/baselines/reference/filterNamespace_import.symbols b/tests/baselines/reference/filterNamespace_import.symbols index f38ea7cc983c9..889fa5fe1155a 100644 --- a/tests/baselines/reference/filterNamespace_import.symbols +++ b/tests/baselines/reference/filterNamespace_import.symbols @@ -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)) diff --git a/tests/baselines/reference/filterNamespace_import.types b/tests/baselines/reference/filterNamespace_import.types index ef9ad8a6e269b..162de035c4cda 100644 --- a/tests/baselines/reference/filterNamespace_import.types +++ b/tests/baselines/reference/filterNamespace_import.types @@ -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; } diff --git a/tests/baselines/reference/generic.symbols b/tests/baselines/reference/generic.symbols index 88625de90732d..a3503b971269d 100644 --- a/tests/baselines/reference/generic.symbols +++ b/tests/baselines/reference/generic.symbols @@ -6,7 +6,7 @@ export class A { 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 === diff --git a/tests/baselines/reference/generic.types b/tests/baselines/reference/generic.types index abe6f1da4a0a5..04bced36a04a7 100644 --- a/tests/baselines/reference/generic.types +++ b/tests/baselines/reference/generic.types @@ -4,30 +4,30 @@ export class A { a!: T } >a : T export type { A as B }; ->A : A +>A : typeof A >B : A === /b.ts === import type { A } from './a'; ->A : import("/a").A +>A : A import { B } from './a'; ->B : any +>B : typeof A let a: A = { a: "" }; ->a : import("/a").A +>a : A >{ a: "" } : { a: string; } >a : string >"" : "" let b: B = { a: 3 }; ->b : import("/a").A +>b : A >{ a: 3 } : { a: number; } >a : number >3 : 3 let c: A = {}; ->c : import("/a").A +>c : A >{} : {} let d: B = { a: "" }; diff --git a/tests/baselines/reference/importClause_default.errors.txt b/tests/baselines/reference/importClause_default.errors.txt index 99345c4102f4c..66e742f8cd7bd 100644 --- a/tests/baselines/reference/importClause_default.errors.txt +++ b/tests/baselines/reference/importClause_default.errors.txt @@ -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: '' }; \ No newline at end of file diff --git a/tests/baselines/reference/importClause_default.symbols b/tests/baselines/reference/importClause_default.symbols index 3c13a061eaa23..88d8f830234d1 100644 --- a/tests/baselines/reference/importClause_default.symbols +++ b/tests/baselines/reference/importClause_default.symbols @@ -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)) diff --git a/tests/baselines/reference/importClause_default.types b/tests/baselines/reference/importClause_default.types index 47ab1c72d607a..f924c2c22f959 100644 --- a/tests/baselines/reference/importClause_default.types +++ b/tests/baselines/reference/importClause_default.types @@ -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 >'' : "" diff --git a/tests/baselines/reference/importClause_namedImports.errors.txt b/tests/baselines/reference/importClause_namedImports.errors.txt index c5cc2bb326006..b33a4fe5bc6ab 100644 --- a/tests/baselines/reference/importClause_namedImports.errors.txt +++ b/tests/baselines/reference/importClause_namedImports.errors.txt @@ -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; diff --git a/tests/baselines/reference/importClause_namedImports.symbols b/tests/baselines/reference/importClause_namedImports.symbols index a21e8d8cba2bb..077b86f4c0126 100644 --- a/tests/baselines/reference/importClause_namedImports.symbols +++ b/tests/baselines/reference/importClause_namedImports.symbols @@ -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)) diff --git a/tests/baselines/reference/importClause_namedImports.types b/tests/baselines/reference/importClause_namedImports.types index a9c43fcf582ad..8a96772a677f5 100644 --- a/tests/baselines/reference/importClause_namedImports.types +++ b/tests/baselines/reference/importClause_namedImports.types @@ -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 diff --git a/tests/baselines/reference/importClause_namespaceImport.errors.txt b/tests/baselines/reference/importClause_namespaceImport.errors.txt index 04d8dceddd02c..a4c543d7f96a5 100644 --- a/tests/baselines/reference/importClause_namespaceImport.errors.txt +++ b/tests/baselines/reference/importClause_namespaceImport.errors.txt @@ -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'. diff --git a/tests/baselines/reference/importClause_namespaceImport.symbols b/tests/baselines/reference/importClause_namespaceImport.symbols index 4242b05a4ca9d..f2133f201cbba 100644 --- a/tests/baselines/reference/importClause_namespaceImport.symbols +++ b/tests/baselines/reference/importClause_namespaceImport.symbols @@ -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 = ""; >c : Symbol(c, Decl(b.ts, 6, 5)) diff --git a/tests/baselines/reference/importClause_namespaceImport.types b/tests/baselines/reference/importClause_namespaceImport.types index 319edbd5632c3..471bf17367720 100644 --- a/tests/baselines/reference/importClause_namespaceImport.types +++ b/tests/baselines/reference/importClause_namespaceImport.types @@ -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 >{} : {} diff --git a/tests/baselines/reference/importsNotUsedAsValues_error.errors.txt b/tests/baselines/reference/importsNotUsedAsValues_error.errors.txt index 591a8c643bf68..8fd9453361765 100644 --- a/tests/baselines/reference/importsNotUsedAsValues_error.errors.txt +++ b/tests/baselines/reference/importsNotUsedAsValues_error.errors.txt @@ -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. - \ No newline at end of file + +==== /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); \ No newline at end of file diff --git a/tests/baselines/reference/importsNotUsedAsValues_error.js b/tests/baselines/reference/importsNotUsedAsValues_error.js index 124925eaeda53..57f5312f0e3af 100644 --- a/tests/baselines/reference/importsNotUsedAsValues_error.js +++ b/tests/baselines/reference/importsNotUsedAsValues_error.js @@ -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); diff --git a/tests/baselines/reference/importsNotUsedAsValues_error.symbols b/tests/baselines/reference/importsNotUsedAsValues_error.symbols index 0726f61086fa5..bc6b9ec5be807 100644 --- a/tests/baselines/reference/importsNotUsedAsValues_error.symbols +++ b/tests/baselines/reference/importsNotUsedAsValues_error.symbols @@ -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)) + diff --git a/tests/baselines/reference/importsNotUsedAsValues_error.types b/tests/baselines/reference/importsNotUsedAsValues_error.types index 5b166c47e684e..692541840ec16 100644 --- a/tests/baselines/reference/importsNotUsedAsValues_error.types +++ b/tests/baselines/reference/importsNotUsedAsValues_error.types @@ -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 + diff --git a/tests/baselines/reference/namespaceImportTypeQuery.errors.txt b/tests/baselines/reference/namespaceImportTypeQuery.errors.txt new file mode 100644 index 0000000000000..5036215385d45 --- /dev/null +++ b/tests/baselines/reference/namespaceImportTypeQuery.errors.txt @@ -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; + \ No newline at end of file diff --git a/tests/baselines/reference/namespaceImportTypeQuery.js b/tests/baselines/reference/namespaceImportTypeQuery.js new file mode 100644 index 0000000000000..2ecc28ad362e4 --- /dev/null +++ b/tests/baselines/reference/namespaceImportTypeQuery.js @@ -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; diff --git a/tests/baselines/reference/namespaceImportTypeQuery.symbols b/tests/baselines/reference/namespaceImportTypeQuery.symbols new file mode 100644 index 0000000000000..9851b31b6b001 --- /dev/null +++ b/tests/baselines/reference/namespaceImportTypeQuery.symbols @@ -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)) + diff --git a/tests/baselines/reference/namespaceImportTypeQuery.types b/tests/baselines/reference/namespaceImportTypeQuery.types new file mode 100644 index 0000000000000..273a46b1507bc --- /dev/null +++ b/tests/baselines/reference/namespaceImportTypeQuery.types @@ -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 + diff --git a/tests/baselines/reference/namespaceMemberAccess.errors.txt b/tests/baselines/reference/namespaceMemberAccess.errors.txt new file mode 100644 index 0000000000000..c2f85e7941d8a --- /dev/null +++ b/tests/baselines/reference/namespaceMemberAccess.errors.txt @@ -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")'. \ No newline at end of file diff --git a/tests/baselines/reference/namespaceMemberAccess.js b/tests/baselines/reference/namespaceMemberAccess.js new file mode 100644 index 0000000000000..2ab4b6e11fbe6 --- /dev/null +++ b/tests/baselines/reference/namespaceMemberAccess.js @@ -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; diff --git a/tests/baselines/reference/namespaceMemberAccess.symbols b/tests/baselines/reference/namespaceMemberAccess.symbols new file mode 100644 index 0000000000000..d9d2bfaf77027 --- /dev/null +++ b/tests/baselines/reference/namespaceMemberAccess.symbols @@ -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)) + diff --git a/tests/baselines/reference/namespaceMemberAccess.types b/tests/baselines/reference/namespaceMemberAccess.types new file mode 100644 index 0000000000000..a86a4c27b742e --- /dev/null +++ b/tests/baselines/reference/namespaceMemberAccess.types @@ -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 + diff --git a/tests/baselines/reference/renamed.symbols b/tests/baselines/reference/renamed.symbols index 8af253a8c0370..3a39567c2d7c3 100644 --- a/tests/baselines/reference/renamed.symbols +++ b/tests/baselines/reference/renamed.symbols @@ -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 === diff --git a/tests/baselines/reference/renamed.types b/tests/baselines/reference/renamed.types index 85a9bfcc4002c..391c686dae7eb 100644 --- a/tests/baselines/reference/renamed.types +++ b/tests/baselines/reference/renamed.types @@ -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 >{} : {} diff --git a/tests/baselines/reference/topLevelAwait(module=esnext,target=es2015).errors.txt b/tests/baselines/reference/topLevelAwait(module=esnext,target=es2015).errors.txt index 10de2df71c67a..058acd93f42ab 100644 --- a/tests/baselines/reference/topLevelAwait(module=esnext,target=es2015).errors.txt +++ b/tests/baselines/reference/topLevelAwait(module=esnext,target=es2015).errors.txt @@ -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. \ No newline at end of file diff --git a/tests/baselines/reference/topLevelAwait(module=system,target=es2015).errors.txt b/tests/baselines/reference/topLevelAwait(module=system,target=es2015).errors.txt index 10de2df71c67a..058acd93f42ab 100644 --- a/tests/baselines/reference/topLevelAwait(module=system,target=es2015).errors.txt +++ b/tests/baselines/reference/topLevelAwait(module=system,target=es2015).errors.txt @@ -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. \ No newline at end of file diff --git a/tests/baselines/reference/typeQuery.js b/tests/baselines/reference/typeQuery.js new file mode 100644 index 0000000000000..8ad78d2fd10dc --- /dev/null +++ b/tests/baselines/reference/typeQuery.js @@ -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; diff --git a/tests/baselines/reference/typeQuery.symbols b/tests/baselines/reference/typeQuery.symbols new file mode 100644 index 0000000000000..960eddb71a4f9 --- /dev/null +++ b/tests/baselines/reference/typeQuery.symbols @@ -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)) + diff --git a/tests/baselines/reference/typeQuery.types b/tests/baselines/reference/typeQuery.types new file mode 100644 index 0000000000000..f1218cbc85eff --- /dev/null +++ b/tests/baselines/reference/typeQuery.types @@ -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 + diff --git a/tests/cases/conformance/externalModules/typeOnly/ambient.ts b/tests/cases/conformance/externalModules/typeOnly/ambient.ts new file mode 100644 index 0000000000000..2632018f7e2c5 --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/ambient.ts @@ -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 {} +} diff --git a/tests/cases/conformance/externalModules/typeOnly/chained2.ts b/tests/cases/conformance/externalModules/typeOnly/chained2.ts new file mode 100644 index 0000000000000..1856fa91e5237 --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/chained2.ts @@ -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 = {}; diff --git a/tests/cases/conformance/externalModules/typeOnly/computedPropertyName.ts b/tests/cases/conformance/externalModules/typeOnly/computedPropertyName.ts new file mode 100644 index 0000000000000..9f64657a97701 --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/computedPropertyName.ts @@ -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; +} diff --git a/tests/cases/conformance/externalModules/typeOnly/importsNotUsedAsValues_error.ts b/tests/cases/conformance/externalModules/typeOnly/importsNotUsedAsValues_error.ts index 6a83db2402c01..aa67936654d12 100644 --- a/tests/cases/conformance/externalModules/typeOnly/importsNotUsedAsValues_error.ts +++ b/tests/cases/conformance/externalModules/typeOnly/importsNotUsedAsValues_error.ts @@ -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); \ No newline at end of file diff --git a/tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery.ts b/tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery.ts new file mode 100644 index 0000000000000..10e8e020158e8 --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery.ts @@ -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; diff --git a/tests/cases/conformance/externalModules/typeOnly/namespaceMemberAccess.ts b/tests/cases/conformance/externalModules/typeOnly/namespaceMemberAccess.ts new file mode 100644 index 0000000000000..98338e054bd11 --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/namespaceMemberAccess.ts @@ -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; \ No newline at end of file diff --git a/tests/cases/conformance/externalModules/typeOnly/typeQuery.ts b/tests/cases/conformance/externalModules/typeOnly/typeQuery.ts new file mode 100644 index 0000000000000..ad481dbd272c9 --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/typeQuery.ts @@ -0,0 +1,6 @@ +// @Filename: /a.ts +export class A { } + +// @Filename: /b.ts +import type { A } from './a'; +let AConstructor: typeof A;