Skip to content

Commit

Permalink
Emit declarations using alternative containing modules for types expo…
Browse files Browse the repository at this point in the history
…rted using separate export statements (#56857)
  • Loading branch information
Andarist authored Jan 9, 2024
1 parent bc74ec4 commit 4557e34
Show file tree
Hide file tree
Showing 9 changed files with 3,264 additions and 23 deletions.
61 changes: 38 additions & 23 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5602,6 +5602,44 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const container = getParentOfSymbol(symbol);
// Type parameters end up in the `members` lists but are not externally visible
if (container && !(symbol.flags & SymbolFlags.TypeParameter)) {
return getWithAlternativeContainers(container);
}
const candidates = mapDefined(symbol.declarations, d => {
if (!isAmbientModule(d) && d.parent) {
// direct children of a module
if (hasNonGlobalAugmentationExternalModuleSymbol(d.parent)) {
return getSymbolOfDeclaration(d.parent as Declaration);
}
// export ='d member of an ambient module
if (isModuleBlock(d.parent) && d.parent.parent && resolveExternalModuleSymbol(getSymbolOfDeclaration(d.parent.parent)) === symbol) {
return getSymbolOfDeclaration(d.parent.parent);
}
}
if (isClassExpression(d) && isBinaryExpression(d.parent) && d.parent.operatorToken.kind === SyntaxKind.EqualsToken && isAccessExpression(d.parent.left) && isEntityNameExpression(d.parent.left.expression)) {
if (isModuleExportsAccessExpression(d.parent.left) || isExportsIdentifier(d.parent.left.expression)) {
return getSymbolOfDeclaration(getSourceFileOfNode(d));
}
checkExpressionCached(d.parent.left.expression);
return getNodeLinks(d.parent.left.expression).resolvedSymbol;
}
});
if (!length(candidates)) {
return undefined;
}
const containers = mapDefined(candidates, candidate => getAliasForSymbolInContainer(candidate, symbol) ? candidate : undefined);

let bestContainers: Symbol[] = [];
let alternativeContainers: Symbol[] = [];

for (const container of containers) {
const [bestMatch, ...rest] = getWithAlternativeContainers(container);
bestContainers = append(bestContainers, bestMatch);
alternativeContainers = addRange(alternativeContainers, rest);
}

return concatenate(bestContainers, alternativeContainers);

function getWithAlternativeContainers(container: Symbol) {
const additionalContainers = mapDefined(container.declarations, fileSymbolIfFileSymbolExportEqualsContainer);
const reexportContainers = enclosingDeclaration && getAlternativeContainingModules(symbol, enclosingDeclaration);
const objectLiteralContainer = getVariableDeclarationOfObjectLiteral(container, meaning);
Expand Down Expand Up @@ -5630,29 +5668,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
res = addRange(res, reexportContainers);
return res;
}
const candidates = mapDefined(symbol.declarations, d => {
if (!isAmbientModule(d) && d.parent) {
// direct children of a module
if (hasNonGlobalAugmentationExternalModuleSymbol(d.parent)) {
return getSymbolOfDeclaration(d.parent as Declaration);
}
// export ='d member of an ambient module
if (isModuleBlock(d.parent) && d.parent.parent && resolveExternalModuleSymbol(getSymbolOfDeclaration(d.parent.parent)) === symbol) {
return getSymbolOfDeclaration(d.parent.parent);
}
}
if (isClassExpression(d) && isBinaryExpression(d.parent) && d.parent.operatorToken.kind === SyntaxKind.EqualsToken && isAccessExpression(d.parent.left) && isEntityNameExpression(d.parent.left.expression)) {
if (isModuleExportsAccessExpression(d.parent.left) || isExportsIdentifier(d.parent.left.expression)) {
return getSymbolOfDeclaration(getSourceFileOfNode(d));
}
checkExpressionCached(d.parent.left.expression);
return getNodeLinks(d.parent.left.expression).resolvedSymbol;
}
});
if (!length(candidates)) {
return undefined;
}
return mapDefined(candidates, candidate => getAliasForSymbolInContainer(candidate, symbol) ? candidate : undefined);

function fileSymbolIfFileSymbolExportEqualsContainer(d: Declaration) {
return container && getFileSymbolIfFileSymbolExportEqualsContainer(d, container);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
//// [tests/cases/compiler/declarationEmitUsingAlternativeContainingModules1.ts] ////

//// [useQuery-CPqkvEsh.d.ts]
type QueryKey = ReadonlyArray<unknown>;

interface Register {}

type DefaultError = Register extends {
defaultError: infer TError;
}
? TError
: Error;

type ShouldRetryFunction<TError = DefaultError> = (
failureCount: number,
error: TError,
) => boolean;
type RetryValue<TError> = boolean | number | ShouldRetryFunction<TError>;

type QueryFunctionContext<
TQueryKey extends QueryKey = QueryKey,
TPageParam = never,
> = [TPageParam] extends [never]
? {
queryKey: TQueryKey;
}
: {
queryKey: TQueryKey;
pageParam: TPageParam;
};

type QueryFunction<
T = unknown,
TQueryKey extends QueryKey = QueryKey,
TPageParam = never,
> = (context: QueryFunctionContext<TQueryKey, TPageParam>) => T | Promise<T>;

interface QueryOptions<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
TPageParam = never,
> {
retry?: RetryValue<TError>;
queryFn?: QueryFunction<TQueryFnData, TQueryKey, TPageParam>;
queryKey?: TQueryKey;
initialData?: TData;
initialDataUpdatedAt?: number | (() => number | undefined);
}

interface QueryObserverOptions<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
TQueryData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
TPageParam = never,
> extends QueryOptions<
TQueryFnData,
TError,
TQueryData,
TQueryKey,
TPageParam
> {
enabled?: boolean;
refetchInterval?: number;
select?: (data: TQueryData) => TData;
}

type UseQueryOptions<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
TQueryData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
> = {
[Property in keyof QueryObserverOptions<
TQueryFnData,
TError,
TData,
TQueryData,
TQueryKey
>]: QueryObserverOptions<
TQueryFnData,
TError,
TData,
TQueryData,
TQueryKey
>[Property];
};

type UndefinedInitialQueryOptions<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
> = UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey> & {
initialData?: undefined;
};

interface QueryObserverBaseResult<TData = unknown, TError = DefaultError> {
data: TData | undefined;
dataUpdatedAt: number;
error: TError | null;
errorUpdatedAt: number;
failureCount: number;
failureReason: TError | null;
errorUpdateCount: number;
isError: boolean;
isFetched: boolean;
isFetchedAfterMount: boolean;
isFetching: boolean;
isLoading: boolean;
isPending: boolean;
isLoadingError: boolean;
isInitialLoading: boolean;
isPaused: boolean;
isPlaceholderData: boolean;
isRefetchError: boolean;
isRefetching: boolean;
isStale: boolean;
isSuccess: boolean;
}

interface QueryObserverSuccessResult<TData = unknown, TError = DefaultError>
extends QueryObserverBaseResult<TData, TError> {
data: TData;
error: null;
isError: false;
isPending: false;
isLoadingError: false;
isRefetchError: false;
isSuccess: true;
status: "success";
}

type DefinedQueryObserverResult<
TData = unknown,
TError = DefaultError,
> = QueryObserverSuccessResult<TData, TError>;
type QueryObserverResult<
TData = unknown,
TError = DefaultError,
> = DefinedQueryObserverResult<TData, TError>;

type ToRef<T> = {
value: T;
};

type UseBaseQueryReturnType<
TData,
TError,
Result = QueryObserverResult<TData, TError>,
> = {
[K in keyof Result]: K extends
| "fetchNextPage"
| "fetchPreviousPage"
| "refetch"
? Result[K]
: ToRef<Readonly<Result>[K]>;
} & {
suspense: () => Promise<Result>;
};

type UseQueryReturnType<TData, TError> = UseBaseQueryReturnType<TData, TError>;

declare function useQuery<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
>(
options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
): UseQueryReturnType<TData, TError>;

export { type UseQueryReturnType, useQuery };

//// [index.d.ts]
export { UseQueryReturnType, useQuery } from './useQuery-CPqkvEsh.js';

//// [package.json]
{
"name": "@tanstack/vue-query",
"type": "module",
"exports": {
".": {
"import": {
"types": "./build/modern/index.d.ts",
"default": "./build/modern/index.js"
},
"require": {
"types": "./build/modern/index.d.cts",
"default": "./build/modern/index.cjs"
}
}
}
}

//// [index.mts]
import { useQuery } from '@tanstack/vue-query'

const baseUrl = 'https://api.publicapis.org/'

interface IEntry {
API: string
Description: string
Auth: string
HTTPS: boolean
Cors: string
Link: string
Category: string
}

const testApi = {
getEntries: (): Promise<IEntry[]> => {
return fetch(baseUrl + 'entries')
.then((res) => res.json())
.then((data) => data.entries)
.catch((err) => console.log(err))
}
}

const entryKeys = {
all: ['entries'] as const,
list: () => [...entryKeys.all, 'list'] as const
}

export const useEntries = () => {
return useQuery({
queryKey: entryKeys.list(),
queryFn: testApi.getEntries,
select: (data) => data.slice(0, 10)
})
}


//// [index.mjs]
import { useQuery } from '@tanstack/vue-query';
const baseUrl = 'https://api.publicapis.org/';
const testApi = {
getEntries: () => {
return fetch(baseUrl + 'entries')
.then((res) => res.json())
.then((data) => data.entries)
.catch((err) => console.log(err));
}
};
const entryKeys = {
all: ['entries'],
list: () => [...entryKeys.all, 'list']
};
export const useEntries = () => {
return useQuery({
queryKey: entryKeys.list(),
queryFn: testApi.getEntries,
select: (data) => data.slice(0, 10)
});
};


//// [index.d.mts]
interface IEntry {
API: string;
Description: string;
Auth: string;
HTTPS: boolean;
Cors: string;
Link: string;
Category: string;
}
export declare const useEntries: () => import("@tanstack/vue-query").UseQueryReturnType<IEntry[], Error>;
export {};
Loading

0 comments on commit 4557e34

Please sign in to comment.