diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 50cf05bad962d..eedb0515d0250 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14914,7 +14914,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const [childTypeParameter = declaration.parent, grandParent] = walkUpParenthesizedTypesAndGetParentAndChild(declaration.parent.parent); if (grandParent.kind === SyntaxKind.TypeReference && !omitTypeReferences) { const typeReference = grandParent as TypeReferenceNode; - const typeParameters = getTypeParametersForTypeReference(typeReference); + const typeParameters = getTypeParametersForTypeReferenceOrImport(typeReference); if (typeParameters) { const index = typeReference.typeArguments!.indexOf(childTypeParameter as TypeNode); if (index < typeParameters.length) { @@ -17943,13 +17943,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getInstantiationExpressionType(getTypeOfSymbol(symbol), node); // intentionally doesn't use resolved symbol so type is cached as expected on the alias } else { - const type = tryGetDeclaredTypeOfSymbol(resolvedSymbol); // call this first to ensure typeParameters is populated (if applicable) - const typeParameters = type && getTypeParametersForTypeAndSymbol(type, resolvedSymbol); - if (node.typeArguments && typeParameters) { - addLazyDiagnostic(() => { - checkTypeArgumentConstraints(node, typeParameters); - }); - } return getTypeReferenceType(node, resolvedSymbol); // getTypeReferenceType doesn't handle aliases - it must get the resolved symbol } } @@ -38325,8 +38318,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } - function getTypeParametersForTypeReference(node: TypeReferenceNode | ExpressionWithTypeArguments) { - const type = getTypeFromTypeReference(node); + function getTypeParametersForTypeReferenceOrImport(node: TypeReferenceNode | ExpressionWithTypeArguments | ImportTypeNode) { + const type = getTypeFromTypeNode(node); if (!isErrorType(type)) { const symbol = getNodeLinks(node).resolvedSymbol; if (symbol) { @@ -38346,11 +38339,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } forEach(node.typeArguments, checkSourceElement); - const type = getTypeFromTypeReference(node); + checkTypeReferenceOrImport(node); + } + + function checkTypeReferenceOrImport(node: TypeReferenceNode | ExpressionWithTypeArguments | ImportTypeNode) { + const type = getTypeFromTypeNode(node); if (!isErrorType(type)) { if (node.typeArguments) { addLazyDiagnostic(() => { - const typeParameters = getTypeParametersForTypeReference(node); + const typeParameters = getTypeParametersForTypeReferenceOrImport(node); if (typeParameters) { checkTypeArgumentConstraints(node, typeParameters); } @@ -38372,7 +38369,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTypeArgumentConstraint(node: TypeNode): Type | undefined { const typeReferenceNode = tryCast(node.parent, isTypeReferenceType); if (!typeReferenceNode) return undefined; - const typeParameters = getTypeParametersForTypeReference(typeReferenceNode); + const typeParameters = getTypeParametersForTypeReferenceOrImport(typeReferenceNode); if (!typeParameters) return undefined; const constraint = getConstraintOfTypeParameter(typeParameters[typeReferenceNode.typeArguments!.indexOf(node)]); return constraint && instantiateType(constraint, createTypeMapper(typeParameters, getEffectiveTypeArguments(typeReferenceNode, typeParameters))); @@ -38575,7 +38572,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - getTypeFromTypeNode(node); + checkTypeReferenceOrImport(node); } function checkNamedTupleMember(node: NamedTupleMember) { diff --git a/tests/baselines/reference/spuriousCircularityOnTypeImport.js b/tests/baselines/reference/spuriousCircularityOnTypeImport.js new file mode 100644 index 0000000000000..53ccf9f8a3f14 --- /dev/null +++ b/tests/baselines/reference/spuriousCircularityOnTypeImport.js @@ -0,0 +1,28 @@ +//// [tests/cases/compiler/spuriousCircularityOnTypeImport.ts] //// + +//// [types.ts] +export type SelectorMap unknown>> = { + [key in keyof T]: T[key]; +}; + +//// [index.ts] +export type SelectorMap unknown>> = { + [key in keyof T]: T[key]; +}; + +export declare const value2: { + sliceSelectors: >(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters }; +}; + +export declare const value3: { + sliceSelectors: >(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters }; +}; + + + +//// [types.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [index.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/tests/baselines/reference/spuriousCircularityOnTypeImport.symbols b/tests/baselines/reference/spuriousCircularityOnTypeImport.symbols new file mode 100644 index 0000000000000..a786b23d24f41 --- /dev/null +++ b/tests/baselines/reference/spuriousCircularityOnTypeImport.symbols @@ -0,0 +1,67 @@ +=== tests/cases/compiler/types.ts === +export type SelectorMap unknown>> = { +>SelectorMap : Symbol(SelectorMap, Decl(types.ts, 0, 0)) +>T : Symbol(T, Decl(types.ts, 0, 24)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>params : Symbol(params, Decl(types.ts, 0, 50)) + + [key in keyof T]: T[key]; +>key : Symbol(key, Decl(types.ts, 1, 5)) +>T : Symbol(T, Decl(types.ts, 0, 24)) +>T : Symbol(T, Decl(types.ts, 0, 24)) +>key : Symbol(key, Decl(types.ts, 1, 5)) + +}; + +=== tests/cases/compiler/index.ts === +export type SelectorMap unknown>> = { +>SelectorMap : Symbol(SelectorMap, Decl(index.ts, 0, 0)) +>T : Symbol(T, Decl(index.ts, 0, 24)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>params : Symbol(params, Decl(index.ts, 0, 50)) + + [key in keyof T]: T[key]; +>key : Symbol(key, Decl(index.ts, 1, 5)) +>T : Symbol(T, Decl(index.ts, 0, 24)) +>T : Symbol(T, Decl(index.ts, 0, 24)) +>key : Symbol(key, Decl(index.ts, 1, 5)) + +}; + +export declare const value2: { +>value2 : Symbol(value2, Decl(index.ts, 4, 20)) + + sliceSelectors: >(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters }; +>sliceSelectors : Symbol(sliceSelectors, Decl(index.ts, 4, 30)) +>FuncMap : Symbol(FuncMap, Decl(index.ts, 5, 21)) +>SelectorMap : Symbol(SelectorMap, Decl(types.ts, 0, 0)) +>FuncMap : Symbol(FuncMap, Decl(index.ts, 5, 21)) +>selectorsBySlice : Symbol(selectorsBySlice, Decl(index.ts, 5, 77)) +>FuncMap : Symbol(FuncMap, Decl(index.ts, 5, 21)) +>P : Symbol(P, Decl(index.ts, 5, 110)) +>FuncMap : Symbol(FuncMap, Decl(index.ts, 5, 21)) +>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --)) +>FuncMap : Symbol(FuncMap, Decl(index.ts, 5, 21)) +>P : Symbol(P, Decl(index.ts, 5, 110)) + +}; + +export declare const value3: { +>value3 : Symbol(value3, Decl(index.ts, 8, 20)) + + sliceSelectors: >(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters }; +>sliceSelectors : Symbol(sliceSelectors, Decl(index.ts, 8, 30)) +>FuncMap : Symbol(FuncMap, Decl(index.ts, 9, 21)) +>SelectorMap : Symbol(SelectorMap, Decl(index.ts, 0, 0)) +>FuncMap : Symbol(FuncMap, Decl(index.ts, 9, 21)) +>selectorsBySlice : Symbol(selectorsBySlice, Decl(index.ts, 9, 59)) +>FuncMap : Symbol(FuncMap, Decl(index.ts, 9, 21)) +>P : Symbol(P, Decl(index.ts, 9, 92)) +>FuncMap : Symbol(FuncMap, Decl(index.ts, 9, 21)) +>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --)) +>FuncMap : Symbol(FuncMap, Decl(index.ts, 9, 21)) +>P : Symbol(P, Decl(index.ts, 9, 92)) + +}; + + diff --git a/tests/baselines/reference/spuriousCircularityOnTypeImport.types b/tests/baselines/reference/spuriousCircularityOnTypeImport.types new file mode 100644 index 0000000000000..5422e4cfae2f5 --- /dev/null +++ b/tests/baselines/reference/spuriousCircularityOnTypeImport.types @@ -0,0 +1,35 @@ +=== tests/cases/compiler/types.ts === +export type SelectorMap unknown>> = { +>SelectorMap : SelectorMap +>params : unknown[] + + [key in keyof T]: T[key]; +}; + +=== tests/cases/compiler/index.ts === +export type SelectorMap unknown>> = { +>SelectorMap : SelectorMap +>params : unknown[] + + [key in keyof T]: T[key]; +}; + +export declare const value2: { +>value2 : { sliceSelectors: >(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters; }; } + + sliceSelectors: >(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters }; +>sliceSelectors : >(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters; } +>selectorsBySlice : FuncMap + +}; + +export declare const value3: { +>value3 : { sliceSelectors: >(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters; }; } + + sliceSelectors: >(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters }; +>sliceSelectors : >(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters; } +>selectorsBySlice : FuncMap + +}; + + diff --git a/tests/cases/compiler/spuriousCircularityOnTypeImport.ts b/tests/cases/compiler/spuriousCircularityOnTypeImport.ts new file mode 100644 index 0000000000000..16dc9820a0e41 --- /dev/null +++ b/tests/cases/compiler/spuriousCircularityOnTypeImport.ts @@ -0,0 +1,20 @@ +// @strict: true + +// @filename: types.ts +export type SelectorMap unknown>> = { + [key in keyof T]: T[key]; +}; + +// @filename: index.ts +export type SelectorMap unknown>> = { + [key in keyof T]: T[key]; +}; + +export declare const value2: { + sliceSelectors: >(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters }; +}; + +export declare const value3: { + sliceSelectors: >(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters }; +}; + diff --git a/tests/cases/fourslash/typeReferenceAndImportDeprecated.ts b/tests/cases/fourslash/typeReferenceAndImportDeprecated.ts new file mode 100644 index 0000000000000..18e5a849db9d7 --- /dev/null +++ b/tests/cases/fourslash/typeReferenceAndImportDeprecated.ts @@ -0,0 +1,38 @@ +/// + +// @filename: types.ts +//// /** @deprecated */ +//// export type SelectorMap unknown>> = { +//// [key in keyof T]: T[key]; +//// }; + +// @filename: index.ts +//// /** @deprecated */ +//// export type SelectorMap unknown>> = { +//// [key in keyof T]: T[key]; +//// }; +//// +//// export declare const value2: { +//// sliceSelectors: |]>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters }; +//// }; +//// +//// export declare const value3: { +//// sliceSelectors: |]>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters }; +//// }; + +goTo.file("index.ts"); +const ranges = test.ranges(); +verify.getSuggestionDiagnostics([ + { + "code": 6385, + "message": "'SelectorMap' is deprecated.", + "reportsDeprecated": true, + "range": ranges[0] + }, + { + "code": 6385, + "message": "'SelectorMap' is deprecated.", + "reportsDeprecated": true, + "range": ranges[1] + }, +]);