Skip to content

Commit 4557e34

Browse files
authored
Emit declarations using alternative containing modules for types exported using separate export statements (#56857)
1 parent bc74ec4 commit 4557e34

9 files changed

+3264
-23
lines changed

src/compiler/checker.ts

+38-23
Original file line numberDiff line numberDiff line change
@@ -5602,6 +5602,44 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
56025602
const container = getParentOfSymbol(symbol);
56035603
// Type parameters end up in the `members` lists but are not externally visible
56045604
if (container && !(symbol.flags & SymbolFlags.TypeParameter)) {
5605+
return getWithAlternativeContainers(container);
5606+
}
5607+
const candidates = mapDefined(symbol.declarations, d => {
5608+
if (!isAmbientModule(d) && d.parent) {
5609+
// direct children of a module
5610+
if (hasNonGlobalAugmentationExternalModuleSymbol(d.parent)) {
5611+
return getSymbolOfDeclaration(d.parent as Declaration);
5612+
}
5613+
// export ='d member of an ambient module
5614+
if (isModuleBlock(d.parent) && d.parent.parent && resolveExternalModuleSymbol(getSymbolOfDeclaration(d.parent.parent)) === symbol) {
5615+
return getSymbolOfDeclaration(d.parent.parent);
5616+
}
5617+
}
5618+
if (isClassExpression(d) && isBinaryExpression(d.parent) && d.parent.operatorToken.kind === SyntaxKind.EqualsToken && isAccessExpression(d.parent.left) && isEntityNameExpression(d.parent.left.expression)) {
5619+
if (isModuleExportsAccessExpression(d.parent.left) || isExportsIdentifier(d.parent.left.expression)) {
5620+
return getSymbolOfDeclaration(getSourceFileOfNode(d));
5621+
}
5622+
checkExpressionCached(d.parent.left.expression);
5623+
return getNodeLinks(d.parent.left.expression).resolvedSymbol;
5624+
}
5625+
});
5626+
if (!length(candidates)) {
5627+
return undefined;
5628+
}
5629+
const containers = mapDefined(candidates, candidate => getAliasForSymbolInContainer(candidate, symbol) ? candidate : undefined);
5630+
5631+
let bestContainers: Symbol[] = [];
5632+
let alternativeContainers: Symbol[] = [];
5633+
5634+
for (const container of containers) {
5635+
const [bestMatch, ...rest] = getWithAlternativeContainers(container);
5636+
bestContainers = append(bestContainers, bestMatch);
5637+
alternativeContainers = addRange(alternativeContainers, rest);
5638+
}
5639+
5640+
return concatenate(bestContainers, alternativeContainers);
5641+
5642+
function getWithAlternativeContainers(container: Symbol) {
56055643
const additionalContainers = mapDefined(container.declarations, fileSymbolIfFileSymbolExportEqualsContainer);
56065644
const reexportContainers = enclosingDeclaration && getAlternativeContainingModules(symbol, enclosingDeclaration);
56075645
const objectLiteralContainer = getVariableDeclarationOfObjectLiteral(container, meaning);
@@ -5630,29 +5668,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
56305668
res = addRange(res, reexportContainers);
56315669
return res;
56325670
}
5633-
const candidates = mapDefined(symbol.declarations, d => {
5634-
if (!isAmbientModule(d) && d.parent) {
5635-
// direct children of a module
5636-
if (hasNonGlobalAugmentationExternalModuleSymbol(d.parent)) {
5637-
return getSymbolOfDeclaration(d.parent as Declaration);
5638-
}
5639-
// export ='d member of an ambient module
5640-
if (isModuleBlock(d.parent) && d.parent.parent && resolveExternalModuleSymbol(getSymbolOfDeclaration(d.parent.parent)) === symbol) {
5641-
return getSymbolOfDeclaration(d.parent.parent);
5642-
}
5643-
}
5644-
if (isClassExpression(d) && isBinaryExpression(d.parent) && d.parent.operatorToken.kind === SyntaxKind.EqualsToken && isAccessExpression(d.parent.left) && isEntityNameExpression(d.parent.left.expression)) {
5645-
if (isModuleExportsAccessExpression(d.parent.left) || isExportsIdentifier(d.parent.left.expression)) {
5646-
return getSymbolOfDeclaration(getSourceFileOfNode(d));
5647-
}
5648-
checkExpressionCached(d.parent.left.expression);
5649-
return getNodeLinks(d.parent.left.expression).resolvedSymbol;
5650-
}
5651-
});
5652-
if (!length(candidates)) {
5653-
return undefined;
5654-
}
5655-
return mapDefined(candidates, candidate => getAliasForSymbolInContainer(candidate, symbol) ? candidate : undefined);
56565671

56575672
function fileSymbolIfFileSymbolExportEqualsContainer(d: Declaration) {
56585673
return container && getFileSymbolIfFileSymbolExportEqualsContainer(d, container);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
//// [tests/cases/compiler/declarationEmitUsingAlternativeContainingModules1.ts] ////
2+
3+
//// [useQuery-CPqkvEsh.d.ts]
4+
type QueryKey = ReadonlyArray<unknown>;
5+
6+
interface Register {}
7+
8+
type DefaultError = Register extends {
9+
defaultError: infer TError;
10+
}
11+
? TError
12+
: Error;
13+
14+
type ShouldRetryFunction<TError = DefaultError> = (
15+
failureCount: number,
16+
error: TError,
17+
) => boolean;
18+
type RetryValue<TError> = boolean | number | ShouldRetryFunction<TError>;
19+
20+
type QueryFunctionContext<
21+
TQueryKey extends QueryKey = QueryKey,
22+
TPageParam = never,
23+
> = [TPageParam] extends [never]
24+
? {
25+
queryKey: TQueryKey;
26+
}
27+
: {
28+
queryKey: TQueryKey;
29+
pageParam: TPageParam;
30+
};
31+
32+
type QueryFunction<
33+
T = unknown,
34+
TQueryKey extends QueryKey = QueryKey,
35+
TPageParam = never,
36+
> = (context: QueryFunctionContext<TQueryKey, TPageParam>) => T | Promise<T>;
37+
38+
interface QueryOptions<
39+
TQueryFnData = unknown,
40+
TError = DefaultError,
41+
TData = TQueryFnData,
42+
TQueryKey extends QueryKey = QueryKey,
43+
TPageParam = never,
44+
> {
45+
retry?: RetryValue<TError>;
46+
queryFn?: QueryFunction<TQueryFnData, TQueryKey, TPageParam>;
47+
queryKey?: TQueryKey;
48+
initialData?: TData;
49+
initialDataUpdatedAt?: number | (() => number | undefined);
50+
}
51+
52+
interface QueryObserverOptions<
53+
TQueryFnData = unknown,
54+
TError = DefaultError,
55+
TData = TQueryFnData,
56+
TQueryData = TQueryFnData,
57+
TQueryKey extends QueryKey = QueryKey,
58+
TPageParam = never,
59+
> extends QueryOptions<
60+
TQueryFnData,
61+
TError,
62+
TQueryData,
63+
TQueryKey,
64+
TPageParam
65+
> {
66+
enabled?: boolean;
67+
refetchInterval?: number;
68+
select?: (data: TQueryData) => TData;
69+
}
70+
71+
type UseQueryOptions<
72+
TQueryFnData = unknown,
73+
TError = DefaultError,
74+
TData = TQueryFnData,
75+
TQueryData = TQueryFnData,
76+
TQueryKey extends QueryKey = QueryKey,
77+
> = {
78+
[Property in keyof QueryObserverOptions<
79+
TQueryFnData,
80+
TError,
81+
TData,
82+
TQueryData,
83+
TQueryKey
84+
>]: QueryObserverOptions<
85+
TQueryFnData,
86+
TError,
87+
TData,
88+
TQueryData,
89+
TQueryKey
90+
>[Property];
91+
};
92+
93+
type UndefinedInitialQueryOptions<
94+
TQueryFnData = unknown,
95+
TError = DefaultError,
96+
TData = TQueryFnData,
97+
TQueryKey extends QueryKey = QueryKey,
98+
> = UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey> & {
99+
initialData?: undefined;
100+
};
101+
102+
interface QueryObserverBaseResult<TData = unknown, TError = DefaultError> {
103+
data: TData | undefined;
104+
dataUpdatedAt: number;
105+
error: TError | null;
106+
errorUpdatedAt: number;
107+
failureCount: number;
108+
failureReason: TError | null;
109+
errorUpdateCount: number;
110+
isError: boolean;
111+
isFetched: boolean;
112+
isFetchedAfterMount: boolean;
113+
isFetching: boolean;
114+
isLoading: boolean;
115+
isPending: boolean;
116+
isLoadingError: boolean;
117+
isInitialLoading: boolean;
118+
isPaused: boolean;
119+
isPlaceholderData: boolean;
120+
isRefetchError: boolean;
121+
isRefetching: boolean;
122+
isStale: boolean;
123+
isSuccess: boolean;
124+
}
125+
126+
interface QueryObserverSuccessResult<TData = unknown, TError = DefaultError>
127+
extends QueryObserverBaseResult<TData, TError> {
128+
data: TData;
129+
error: null;
130+
isError: false;
131+
isPending: false;
132+
isLoadingError: false;
133+
isRefetchError: false;
134+
isSuccess: true;
135+
status: "success";
136+
}
137+
138+
type DefinedQueryObserverResult<
139+
TData = unknown,
140+
TError = DefaultError,
141+
> = QueryObserverSuccessResult<TData, TError>;
142+
type QueryObserverResult<
143+
TData = unknown,
144+
TError = DefaultError,
145+
> = DefinedQueryObserverResult<TData, TError>;
146+
147+
type ToRef<T> = {
148+
value: T;
149+
};
150+
151+
type UseBaseQueryReturnType<
152+
TData,
153+
TError,
154+
Result = QueryObserverResult<TData, TError>,
155+
> = {
156+
[K in keyof Result]: K extends
157+
| "fetchNextPage"
158+
| "fetchPreviousPage"
159+
| "refetch"
160+
? Result[K]
161+
: ToRef<Readonly<Result>[K]>;
162+
} & {
163+
suspense: () => Promise<Result>;
164+
};
165+
166+
type UseQueryReturnType<TData, TError> = UseBaseQueryReturnType<TData, TError>;
167+
168+
declare function useQuery<
169+
TQueryFnData = unknown,
170+
TError = DefaultError,
171+
TData = TQueryFnData,
172+
TQueryKey extends QueryKey = QueryKey,
173+
>(
174+
options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
175+
): UseQueryReturnType<TData, TError>;
176+
177+
export { type UseQueryReturnType, useQuery };
178+
179+
//// [index.d.ts]
180+
export { UseQueryReturnType, useQuery } from './useQuery-CPqkvEsh.js';
181+
182+
//// [package.json]
183+
{
184+
"name": "@tanstack/vue-query",
185+
"type": "module",
186+
"exports": {
187+
".": {
188+
"import": {
189+
"types": "./build/modern/index.d.ts",
190+
"default": "./build/modern/index.js"
191+
},
192+
"require": {
193+
"types": "./build/modern/index.d.cts",
194+
"default": "./build/modern/index.cjs"
195+
}
196+
}
197+
}
198+
}
199+
200+
//// [index.mts]
201+
import { useQuery } from '@tanstack/vue-query'
202+
203+
const baseUrl = 'https://api.publicapis.org/'
204+
205+
interface IEntry {
206+
API: string
207+
Description: string
208+
Auth: string
209+
HTTPS: boolean
210+
Cors: string
211+
Link: string
212+
Category: string
213+
}
214+
215+
const testApi = {
216+
getEntries: (): Promise<IEntry[]> => {
217+
return fetch(baseUrl + 'entries')
218+
.then((res) => res.json())
219+
.then((data) => data.entries)
220+
.catch((err) => console.log(err))
221+
}
222+
}
223+
224+
const entryKeys = {
225+
all: ['entries'] as const,
226+
list: () => [...entryKeys.all, 'list'] as const
227+
}
228+
229+
export const useEntries = () => {
230+
return useQuery({
231+
queryKey: entryKeys.list(),
232+
queryFn: testApi.getEntries,
233+
select: (data) => data.slice(0, 10)
234+
})
235+
}
236+
237+
238+
//// [index.mjs]
239+
import { useQuery } from '@tanstack/vue-query';
240+
const baseUrl = 'https://api.publicapis.org/';
241+
const testApi = {
242+
getEntries: () => {
243+
return fetch(baseUrl + 'entries')
244+
.then((res) => res.json())
245+
.then((data) => data.entries)
246+
.catch((err) => console.log(err));
247+
}
248+
};
249+
const entryKeys = {
250+
all: ['entries'],
251+
list: () => [...entryKeys.all, 'list']
252+
};
253+
export const useEntries = () => {
254+
return useQuery({
255+
queryKey: entryKeys.list(),
256+
queryFn: testApi.getEntries,
257+
select: (data) => data.slice(0, 10)
258+
});
259+
};
260+
261+
262+
//// [index.d.mts]
263+
interface IEntry {
264+
API: string;
265+
Description: string;
266+
Auth: string;
267+
HTTPS: boolean;
268+
Cors: string;
269+
Link: string;
270+
Category: string;
271+
}
272+
export declare const useEntries: () => import("@tanstack/vue-query").UseQueryReturnType<IEntry[], Error>;
273+
export {};

0 commit comments

Comments
 (0)