Skip to content

Commit 3471bd7

Browse files
authored
Fix type import node circularity errors in eager diagnostic mode, deprecations (#52861)
1 parent 8adc460 commit 3471bd7

6 files changed

+199
-14
lines changed

src/compiler/checker.ts

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14915,7 +14915,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1491514915
const [childTypeParameter = declaration.parent, grandParent] = walkUpParenthesizedTypesAndGetParentAndChild(declaration.parent.parent);
1491614916
if (grandParent.kind === SyntaxKind.TypeReference && !omitTypeReferences) {
1491714917
const typeReference = grandParent as TypeReferenceNode;
14918-
const typeParameters = getTypeParametersForTypeReference(typeReference);
14918+
const typeParameters = getTypeParametersForTypeReferenceOrImport(typeReference);
1491914919
if (typeParameters) {
1492014920
const index = typeReference.typeArguments!.indexOf(childTypeParameter as TypeNode);
1492114921
if (index < typeParameters.length) {
@@ -17944,13 +17944,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1794417944
return getInstantiationExpressionType(getTypeOfSymbol(symbol), node); // intentionally doesn't use resolved symbol so type is cached as expected on the alias
1794517945
}
1794617946
else {
17947-
const type = tryGetDeclaredTypeOfSymbol(resolvedSymbol); // call this first to ensure typeParameters is populated (if applicable)
17948-
const typeParameters = type && getTypeParametersForTypeAndSymbol(type, resolvedSymbol);
17949-
if (node.typeArguments && typeParameters) {
17950-
addLazyDiagnostic(() => {
17951-
checkTypeArgumentConstraints(node, typeParameters);
17952-
});
17953-
}
1795417947
return getTypeReferenceType(node, resolvedSymbol); // getTypeReferenceType doesn't handle aliases - it must get the resolved symbol
1795517948
}
1795617949
}
@@ -38326,8 +38319,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3832638319
return undefined;
3832738320
}
3832838321

38329-
function getTypeParametersForTypeReference(node: TypeReferenceNode | ExpressionWithTypeArguments) {
38330-
const type = getTypeFromTypeReference(node);
38322+
function getTypeParametersForTypeReferenceOrImport(node: TypeReferenceNode | ExpressionWithTypeArguments | ImportTypeNode) {
38323+
const type = getTypeFromTypeNode(node);
3833138324
if (!isErrorType(type)) {
3833238325
const symbol = getNodeLinks(node).resolvedSymbol;
3833338326
if (symbol) {
@@ -38347,11 +38340,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3834738340
}
3834838341
}
3834938342
forEach(node.typeArguments, checkSourceElement);
38350-
const type = getTypeFromTypeReference(node);
38343+
checkTypeReferenceOrImport(node);
38344+
}
38345+
38346+
function checkTypeReferenceOrImport(node: TypeReferenceNode | ExpressionWithTypeArguments | ImportTypeNode) {
38347+
const type = getTypeFromTypeNode(node);
3835138348
if (!isErrorType(type)) {
3835238349
if (node.typeArguments) {
3835338350
addLazyDiagnostic(() => {
38354-
const typeParameters = getTypeParametersForTypeReference(node);
38351+
const typeParameters = getTypeParametersForTypeReferenceOrImport(node);
3835538352
if (typeParameters) {
3835638353
checkTypeArgumentConstraints(node, typeParameters);
3835738354
}
@@ -38373,7 +38370,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3837338370
function getTypeArgumentConstraint(node: TypeNode): Type | undefined {
3837438371
const typeReferenceNode = tryCast(node.parent, isTypeReferenceType);
3837538372
if (!typeReferenceNode) return undefined;
38376-
const typeParameters = getTypeParametersForTypeReference(typeReferenceNode);
38373+
const typeParameters = getTypeParametersForTypeReferenceOrImport(typeReferenceNode);
3837738374
if (!typeParameters) return undefined;
3837838375
const constraint = getConstraintOfTypeParameter(typeParameters[typeReferenceNode.typeArguments!.indexOf(node)]);
3837938376
return constraint && instantiateType(constraint, createTypeMapper(typeParameters, getEffectiveTypeArguments(typeReferenceNode, typeParameters)));
@@ -38576,7 +38573,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3857638573
}
3857738574
}
3857838575

38579-
getTypeFromTypeNode(node);
38576+
checkTypeReferenceOrImport(node);
3858038577
}
3858138578

3858238579
function checkNamedTupleMember(node: NamedTupleMember) {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//// [tests/cases/compiler/spuriousCircularityOnTypeImport.ts] ////
2+
3+
//// [types.ts]
4+
export type SelectorMap<T extends Record<string, (...params: unknown[]) => unknown>> = {
5+
[key in keyof T]: T[key];
6+
};
7+
8+
//// [index.ts]
9+
export type SelectorMap<T extends Record<string, (...params: unknown[]) => unknown>> = {
10+
[key in keyof T]: T[key];
11+
};
12+
13+
export declare const value2: {
14+
sliceSelectors: <FuncMap extends import('./types').SelectorMap<FuncMap>>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters<FuncMap[P]> };
15+
};
16+
17+
export declare const value3: {
18+
sliceSelectors: <FuncMap extends SelectorMap<FuncMap>>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters<FuncMap[P]> };
19+
};
20+
21+
22+
23+
//// [types.js]
24+
"use strict";
25+
Object.defineProperty(exports, "__esModule", { value: true });
26+
//// [index.js]
27+
"use strict";
28+
Object.defineProperty(exports, "__esModule", { value: true });
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
=== tests/cases/compiler/types.ts ===
2+
export type SelectorMap<T extends Record<string, (...params: unknown[]) => unknown>> = {
3+
>SelectorMap : Symbol(SelectorMap, Decl(types.ts, 0, 0))
4+
>T : Symbol(T, Decl(types.ts, 0, 24))
5+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
6+
>params : Symbol(params, Decl(types.ts, 0, 50))
7+
8+
[key in keyof T]: T[key];
9+
>key : Symbol(key, Decl(types.ts, 1, 5))
10+
>T : Symbol(T, Decl(types.ts, 0, 24))
11+
>T : Symbol(T, Decl(types.ts, 0, 24))
12+
>key : Symbol(key, Decl(types.ts, 1, 5))
13+
14+
};
15+
16+
=== tests/cases/compiler/index.ts ===
17+
export type SelectorMap<T extends Record<string, (...params: unknown[]) => unknown>> = {
18+
>SelectorMap : Symbol(SelectorMap, Decl(index.ts, 0, 0))
19+
>T : Symbol(T, Decl(index.ts, 0, 24))
20+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
21+
>params : Symbol(params, Decl(index.ts, 0, 50))
22+
23+
[key in keyof T]: T[key];
24+
>key : Symbol(key, Decl(index.ts, 1, 5))
25+
>T : Symbol(T, Decl(index.ts, 0, 24))
26+
>T : Symbol(T, Decl(index.ts, 0, 24))
27+
>key : Symbol(key, Decl(index.ts, 1, 5))
28+
29+
};
30+
31+
export declare const value2: {
32+
>value2 : Symbol(value2, Decl(index.ts, 4, 20))
33+
34+
sliceSelectors: <FuncMap extends import('./types').SelectorMap<FuncMap>>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters<FuncMap[P]> };
35+
>sliceSelectors : Symbol(sliceSelectors, Decl(index.ts, 4, 30))
36+
>FuncMap : Symbol(FuncMap, Decl(index.ts, 5, 21))
37+
>SelectorMap : Symbol(SelectorMap, Decl(types.ts, 0, 0))
38+
>FuncMap : Symbol(FuncMap, Decl(index.ts, 5, 21))
39+
>selectorsBySlice : Symbol(selectorsBySlice, Decl(index.ts, 5, 77))
40+
>FuncMap : Symbol(FuncMap, Decl(index.ts, 5, 21))
41+
>P : Symbol(P, Decl(index.ts, 5, 110))
42+
>FuncMap : Symbol(FuncMap, Decl(index.ts, 5, 21))
43+
>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --))
44+
>FuncMap : Symbol(FuncMap, Decl(index.ts, 5, 21))
45+
>P : Symbol(P, Decl(index.ts, 5, 110))
46+
47+
};
48+
49+
export declare const value3: {
50+
>value3 : Symbol(value3, Decl(index.ts, 8, 20))
51+
52+
sliceSelectors: <FuncMap extends SelectorMap<FuncMap>>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters<FuncMap[P]> };
53+
>sliceSelectors : Symbol(sliceSelectors, Decl(index.ts, 8, 30))
54+
>FuncMap : Symbol(FuncMap, Decl(index.ts, 9, 21))
55+
>SelectorMap : Symbol(SelectorMap, Decl(index.ts, 0, 0))
56+
>FuncMap : Symbol(FuncMap, Decl(index.ts, 9, 21))
57+
>selectorsBySlice : Symbol(selectorsBySlice, Decl(index.ts, 9, 59))
58+
>FuncMap : Symbol(FuncMap, Decl(index.ts, 9, 21))
59+
>P : Symbol(P, Decl(index.ts, 9, 92))
60+
>FuncMap : Symbol(FuncMap, Decl(index.ts, 9, 21))
61+
>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --))
62+
>FuncMap : Symbol(FuncMap, Decl(index.ts, 9, 21))
63+
>P : Symbol(P, Decl(index.ts, 9, 92))
64+
65+
};
66+
67+
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
=== tests/cases/compiler/types.ts ===
2+
export type SelectorMap<T extends Record<string, (...params: unknown[]) => unknown>> = {
3+
>SelectorMap : SelectorMap<T>
4+
>params : unknown[]
5+
6+
[key in keyof T]: T[key];
7+
};
8+
9+
=== tests/cases/compiler/index.ts ===
10+
export type SelectorMap<T extends Record<string, (...params: unknown[]) => unknown>> = {
11+
>SelectorMap : SelectorMap<T>
12+
>params : unknown[]
13+
14+
[key in keyof T]: T[key];
15+
};
16+
17+
export declare const value2: {
18+
>value2 : { sliceSelectors: <FuncMap extends import("tests/cases/compiler/types").SelectorMap<FuncMap>>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters<FuncMap[P]>; }; }
19+
20+
sliceSelectors: <FuncMap extends import('./types').SelectorMap<FuncMap>>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters<FuncMap[P]> };
21+
>sliceSelectors : <FuncMap extends import("tests/cases/compiler/types").SelectorMap<FuncMap>>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters<FuncMap[P]>; }
22+
>selectorsBySlice : FuncMap
23+
24+
};
25+
26+
export declare const value3: {
27+
>value3 : { sliceSelectors: <FuncMap extends SelectorMap<FuncMap>>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters<FuncMap[P]>; }; }
28+
29+
sliceSelectors: <FuncMap extends SelectorMap<FuncMap>>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters<FuncMap[P]> };
30+
>sliceSelectors : <FuncMap extends SelectorMap<FuncMap>>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters<FuncMap[P]>; }
31+
>selectorsBySlice : FuncMap
32+
33+
};
34+
35+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// @strict: true
2+
3+
// @filename: types.ts
4+
export type SelectorMap<T extends Record<string, (...params: unknown[]) => unknown>> = {
5+
[key in keyof T]: T[key];
6+
};
7+
8+
// @filename: index.ts
9+
export type SelectorMap<T extends Record<string, (...params: unknown[]) => unknown>> = {
10+
[key in keyof T]: T[key];
11+
};
12+
13+
export declare const value2: {
14+
sliceSelectors: <FuncMap extends import('./types').SelectorMap<FuncMap>>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters<FuncMap[P]> };
15+
};
16+
17+
export declare const value3: {
18+
sliceSelectors: <FuncMap extends SelectorMap<FuncMap>>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters<FuncMap[P]> };
19+
};
20+
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @filename: types.ts
4+
//// /** @deprecated */
5+
//// export type SelectorMap<T extends Record<string, (...params: unknown[]) => unknown>> = {
6+
//// [key in keyof T]: T[key];
7+
//// };
8+
9+
// @filename: index.ts
10+
//// /** @deprecated */
11+
//// export type SelectorMap<T extends Record<string, (...params: unknown[]) => unknown>> = {
12+
//// [key in keyof T]: T[key];
13+
//// };
14+
////
15+
//// export declare const value2: {
16+
//// sliceSelectors: <FuncMap extends [|import('./types').SelectorMap<FuncMap>|]>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters<FuncMap[P]> };
17+
//// };
18+
////
19+
//// export declare const value3: {
20+
//// sliceSelectors: <FuncMap extends [|SelectorMap<FuncMap>|]>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters<FuncMap[P]> };
21+
//// };
22+
23+
goTo.file("index.ts");
24+
const ranges = test.ranges();
25+
verify.getSuggestionDiagnostics([
26+
{
27+
"code": 6385,
28+
"message": "'SelectorMap' is deprecated.",
29+
"reportsDeprecated": true,
30+
"range": ranges[0]
31+
},
32+
{
33+
"code": 6385,
34+
"message": "'SelectorMap' is deprecated.",
35+
"reportsDeprecated": true,
36+
"range": ranges[1]
37+
},
38+
]);

0 commit comments

Comments
 (0)