mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-10 01:43:59 -05:00
Recover from type reuse errors by falling back to inferred type printing (#58720)
This commit is contained in:
committed by
GitHub
parent
59e6620260
commit
22eaccba2a
@@ -8472,17 +8472,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
}
|
||||
let hadError = false;
|
||||
const { finalizeBoundary, startRecoveryScope } = createRecoveryBoundary();
|
||||
const transformed = visitNode(existing, visitExistingNodeTreeSymbols, isTypeNode);
|
||||
if (hadError) {
|
||||
if (!finalizeBoundary()) {
|
||||
return undefined;
|
||||
}
|
||||
context.approximateLength += existing.end - existing.pos;
|
||||
return transformed;
|
||||
|
||||
function visitExistingNodeTreeSymbols(node: Node): Node | undefined {
|
||||
// If there was an error in a sibling node bail early, the result will be discarded anyway
|
||||
if (hadError) return node;
|
||||
const recover = startRecoveryScope();
|
||||
const onExitNewScope = isNewScopeNode(node) ? onEnterNewScope(node) : undefined;
|
||||
const result = visitExistingNodeTreeSymbolsWorker(node);
|
||||
onExitNewScope?.();
|
||||
|
||||
// If there was an error, maybe we can recover by serializing the actual type of the node
|
||||
if (hadError) {
|
||||
if (isTypeNode(node) && !isTypePredicateNode(node)) {
|
||||
recover();
|
||||
return serializeExistingTypeNode(context, node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
// We want to clone the subtree, so when we mark it up with __pos and __end in quickfixes,
|
||||
// we don't get odd behavior because of reused nodes. We also need to clone to _remove_
|
||||
// the position information if the node comes from a different file than the one the node builder
|
||||
@@ -8492,6 +8505,86 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return result === node ? setTextRange(context, factory.cloneNode(result), node) : result;
|
||||
}
|
||||
|
||||
function createRecoveryBoundary() {
|
||||
let unreportedErrors: (() => void)[];
|
||||
const oldTracker = context.tracker;
|
||||
const oldTrackedSymbols = context.trackedSymbols;
|
||||
context.trackedSymbols = [];
|
||||
const oldEncounteredError = context.encounteredError;
|
||||
context.tracker = new SymbolTrackerImpl(context, {
|
||||
...oldTracker.inner,
|
||||
reportCyclicStructureError() {
|
||||
markError(() => oldTracker.reportCyclicStructureError());
|
||||
},
|
||||
reportInaccessibleThisError() {
|
||||
markError(() => oldTracker.reportInaccessibleThisError());
|
||||
},
|
||||
reportInaccessibleUniqueSymbolError() {
|
||||
markError(() => oldTracker.reportInaccessibleUniqueSymbolError());
|
||||
},
|
||||
reportLikelyUnsafeImportRequiredError(specifier) {
|
||||
markError(() => oldTracker.reportLikelyUnsafeImportRequiredError(specifier));
|
||||
},
|
||||
reportNonSerializableProperty(name) {
|
||||
markError(() => oldTracker.reportNonSerializableProperty(name));
|
||||
},
|
||||
trackSymbol(sym, decl, meaning) {
|
||||
const accessibility = isSymbolAccessible(sym, decl, meaning, /*shouldComputeAliasesToMakeVisible*/ false);
|
||||
if (accessibility.accessibility !== SymbolAccessibility.Accessible) {
|
||||
(context.trackedSymbols ??= []).push([sym, decl, meaning]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
moduleResolverHost: context.tracker.moduleResolverHost,
|
||||
}, context.tracker.moduleResolverHost);
|
||||
|
||||
return {
|
||||
startRecoveryScope,
|
||||
finalizeBoundary,
|
||||
};
|
||||
|
||||
function markError(unreportedError: () => void) {
|
||||
hadError = true;
|
||||
(unreportedErrors ??= []).push(unreportedError);
|
||||
}
|
||||
|
||||
function startRecoveryScope() {
|
||||
const initialTrackedSymbolsTop = context.trackedSymbols?.length ?? 0;
|
||||
const unreportedErrorsTop = unreportedErrors?.length ?? 0;
|
||||
return () => {
|
||||
hadError = false;
|
||||
// Reset the tracked symbols to before the error
|
||||
if (context.trackedSymbols) {
|
||||
context.trackedSymbols.length = initialTrackedSymbolsTop;
|
||||
}
|
||||
if (unreportedErrors) {
|
||||
unreportedErrors.length = unreportedErrorsTop;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function finalizeBoundary() {
|
||||
context.tracker = oldTracker;
|
||||
const newTrackedSymbols = context.trackedSymbols;
|
||||
context.trackedSymbols = oldTrackedSymbols;
|
||||
context.encounteredError = oldEncounteredError;
|
||||
|
||||
unreportedErrors?.forEach(fn => fn());
|
||||
if (hadError) {
|
||||
return false;
|
||||
}
|
||||
newTrackedSymbols?.forEach(
|
||||
([symbol, enclosingDeclaration, meaning]) =>
|
||||
context.tracker.trackSymbol(
|
||||
symbol,
|
||||
enclosingDeclaration,
|
||||
meaning,
|
||||
),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
function onEnterNewScope(node: IntroducesNewScopeNode | ConditionalTypeNode) {
|
||||
return enterNewScope(context, node, getParametersInScope(node), getTypeParametersInScope(node));
|
||||
}
|
||||
@@ -8765,13 +8858,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
|
||||
function rewriteModuleSpecifier(parent: ImportTypeNode, lit: StringLiteral) {
|
||||
if (context.bundled || context.enclosingFile !== getSourceFileOfNode(lit)) {
|
||||
const targetFile = getExternalModuleFileFromDeclaration(parent);
|
||||
if (targetFile) {
|
||||
const newName = getSpecifierForModuleSymbol(targetFile.symbol, context);
|
||||
if (newName !== lit.text) {
|
||||
return setOriginalNode(factory.createStringLiteral(newName), lit);
|
||||
let name = lit.text;
|
||||
const nodeSymbol = getNodeLinks(node).resolvedSymbol;
|
||||
const meaning = parent.isTypeOf ? SymbolFlags.Value : SymbolFlags.Type;
|
||||
const parentSymbol = nodeSymbol
|
||||
&& isSymbolAccessible(nodeSymbol, context.enclosingDeclaration, meaning, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible
|
||||
&& lookupSymbolChain(nodeSymbol, context, meaning, /*yieldModuleSymbol*/ true)[0];
|
||||
if (parentSymbol && parentSymbol.flags & SymbolFlags.Module) {
|
||||
name = getSpecifierForModuleSymbol(parentSymbol, context);
|
||||
}
|
||||
else {
|
||||
const targetFile = getExternalModuleFileFromDeclaration(parent);
|
||||
if (targetFile) {
|
||||
name = getSpecifierForModuleSymbol(targetFile.symbol, context);
|
||||
}
|
||||
}
|
||||
if (name.includes("/node_modules/")) {
|
||||
context.encounteredError = true;
|
||||
if (context.tracker.reportLikelyUnsafeImportRequiredError) {
|
||||
context.tracker.reportLikelyUnsafeImportRequiredError(name);
|
||||
}
|
||||
}
|
||||
if (name !== lit.text) {
|
||||
return setOriginalNode(factory.createStringLiteral(name), lit);
|
||||
}
|
||||
}
|
||||
return visitNode(lit, visitExistingNodeTreeSymbols, isStringLiteral)!;
|
||||
}
|
||||
|
||||
61
tests/baselines/reference/declarationEmitUsingTypeAlias2.js
Normal file
61
tests/baselines/reference/declarationEmitUsingTypeAlias2.js
Normal file
@@ -0,0 +1,61 @@
|
||||
//// [tests/cases/compiler/declarationEmitUsingTypeAlias2.ts] ////
|
||||
|
||||
//// [inner.d.ts]
|
||||
export declare type Other = { other: string };
|
||||
export declare type SomeType = { arg: Other };
|
||||
|
||||
//// [other.d.ts]
|
||||
export declare const shouldLookupName: unique symbol;
|
||||
export declare const shouldReuseLocalName: unique symbol;
|
||||
export declare const reuseDepName: unique symbol;
|
||||
export declare const shouldBeElided: unique symbol;
|
||||
export declare const isNotAccessibleShouldError: unique symbol;
|
||||
|
||||
//// [index.d.ts]
|
||||
import { Other } from './inner'
|
||||
import { shouldLookupName, reuseDepName, shouldReuseLocalName, shouldBeElided } from './other'
|
||||
export declare const goodDeclaration: <T>() => () => {
|
||||
/** Other Can't be named in index.ts, but the whole conditional type can be resolved */
|
||||
shouldPrintResult: T extends Other? "O": "N",
|
||||
/** Symbol shouldBeElided should not be present in index.d.ts, it might be since it's tracked before Other is seen and an error reported */
|
||||
shouldPrintResult2: T extends typeof shouldBeElided? Other: "N",
|
||||
/** Specifier should come from module, local path should not be reused */
|
||||
shouldLookupName: typeof import('./other').shouldLookupName,
|
||||
/** This is imported in index so local name should be reused */
|
||||
shouldReuseLocalName: typeof shouldReuseLocalName
|
||||
/** This is NOT imported in index so import should be created */
|
||||
reuseDepName: typeof reuseDepName,
|
||||
}
|
||||
export { shouldLookupName, shouldReuseLocalName, reuseDepName, shouldBeElided };
|
||||
|
||||
//// [package.json]
|
||||
{
|
||||
"name": "some-dep",
|
||||
"exports": {
|
||||
".": "./dist/index.js"
|
||||
}
|
||||
}
|
||||
|
||||
//// [index.ts]
|
||||
import { goodDeclaration, shouldReuseLocalName, shouldBeElided } from "some-dep";
|
||||
export const bar = goodDeclaration<{}>;
|
||||
|
||||
|
||||
|
||||
//// [index.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.bar = void 0;
|
||||
const some_dep_1 = require("some-dep");
|
||||
exports.bar = (some_dep_1.goodDeclaration);
|
||||
|
||||
|
||||
//// [index.d.ts]
|
||||
import { shouldReuseLocalName } from "some-dep";
|
||||
export declare const bar: () => () => {
|
||||
shouldPrintResult: "N";
|
||||
shouldPrintResult2: "N";
|
||||
shouldLookupName: typeof import("some-dep").shouldLookupName;
|
||||
shouldReuseLocalName: typeof shouldReuseLocalName;
|
||||
reuseDepName: typeof import("some-dep").reuseDepName;
|
||||
};
|
||||
@@ -0,0 +1,87 @@
|
||||
//// [tests/cases/compiler/declarationEmitUsingTypeAlias2.ts] ////
|
||||
|
||||
=== node_modules/some-dep/dist/inner.d.ts ===
|
||||
export declare type Other = { other: string };
|
||||
>Other : Symbol(Other, Decl(inner.d.ts, 0, 0))
|
||||
>other : Symbol(other, Decl(inner.d.ts, 0, 29))
|
||||
|
||||
export declare type SomeType = { arg: Other };
|
||||
>SomeType : Symbol(SomeType, Decl(inner.d.ts, 0, 46))
|
||||
>arg : Symbol(arg, Decl(inner.d.ts, 1, 32))
|
||||
>Other : Symbol(Other, Decl(inner.d.ts, 0, 0))
|
||||
|
||||
=== node_modules/some-dep/dist/other.d.ts ===
|
||||
export declare const shouldLookupName: unique symbol;
|
||||
>shouldLookupName : Symbol(shouldLookupName, Decl(other.d.ts, 0, 20))
|
||||
|
||||
export declare const shouldReuseLocalName: unique symbol;
|
||||
>shouldReuseLocalName : Symbol(shouldReuseLocalName, Decl(other.d.ts, 1, 20))
|
||||
|
||||
export declare const reuseDepName: unique symbol;
|
||||
>reuseDepName : Symbol(reuseDepName, Decl(other.d.ts, 2, 20))
|
||||
|
||||
export declare const shouldBeElided: unique symbol;
|
||||
>shouldBeElided : Symbol(shouldBeElided, Decl(other.d.ts, 3, 20))
|
||||
|
||||
export declare const isNotAccessibleShouldError: unique symbol;
|
||||
>isNotAccessibleShouldError : Symbol(isNotAccessibleShouldError, Decl(other.d.ts, 4, 20))
|
||||
|
||||
=== node_modules/some-dep/dist/index.d.ts ===
|
||||
import { Other } from './inner'
|
||||
>Other : Symbol(Other, Decl(index.d.ts, 0, 8))
|
||||
|
||||
import { shouldLookupName, reuseDepName, shouldReuseLocalName, shouldBeElided } from './other'
|
||||
>shouldLookupName : Symbol(shouldLookupName, Decl(index.d.ts, 1, 8))
|
||||
>reuseDepName : Symbol(reuseDepName, Decl(index.d.ts, 1, 26))
|
||||
>shouldReuseLocalName : Symbol(shouldReuseLocalName, Decl(index.d.ts, 1, 40))
|
||||
>shouldBeElided : Symbol(shouldBeElided, Decl(index.d.ts, 1, 62))
|
||||
|
||||
export declare const goodDeclaration: <T>() => () => {
|
||||
>goodDeclaration : Symbol(goodDeclaration, Decl(index.d.ts, 2, 20))
|
||||
>T : Symbol(T, Decl(index.d.ts, 2, 39))
|
||||
|
||||
/** Other Can't be named in index.ts, but the whole conditional type can be resolved */
|
||||
shouldPrintResult: T extends Other? "O": "N",
|
||||
>shouldPrintResult : Symbol(shouldPrintResult, Decl(index.d.ts, 2, 54))
|
||||
>T : Symbol(T, Decl(index.d.ts, 2, 39))
|
||||
>Other : Symbol(Other, Decl(index.d.ts, 0, 8))
|
||||
|
||||
/** Symbol shouldBeElided should not be present in index.d.ts, it might be since it's tracked before Other is seen and an error reported */
|
||||
shouldPrintResult2: T extends typeof shouldBeElided? Other: "N",
|
||||
>shouldPrintResult2 : Symbol(shouldPrintResult2, Decl(index.d.ts, 4, 47))
|
||||
>T : Symbol(T, Decl(index.d.ts, 2, 39))
|
||||
>shouldBeElided : Symbol(shouldBeElided, Decl(index.d.ts, 1, 62))
|
||||
>Other : Symbol(Other, Decl(index.d.ts, 0, 8))
|
||||
|
||||
/** Specifier should come from module, local path should not be reused */
|
||||
shouldLookupName: typeof import('./other').shouldLookupName,
|
||||
>shouldLookupName : Symbol(shouldLookupName, Decl(index.d.ts, 6, 66))
|
||||
>shouldLookupName : Symbol(shouldLookupName, Decl(other.d.ts, 0, 20))
|
||||
|
||||
/** This is imported in index so local name should be reused */
|
||||
shouldReuseLocalName: typeof shouldReuseLocalName
|
||||
>shouldReuseLocalName : Symbol(shouldReuseLocalName, Decl(index.d.ts, 8, 62))
|
||||
>shouldReuseLocalName : Symbol(shouldReuseLocalName, Decl(index.d.ts, 1, 40))
|
||||
|
||||
/** This is NOT imported in index so import should be created */
|
||||
reuseDepName: typeof reuseDepName,
|
||||
>reuseDepName : Symbol(reuseDepName, Decl(index.d.ts, 10, 51))
|
||||
>reuseDepName : Symbol(reuseDepName, Decl(index.d.ts, 1, 26))
|
||||
}
|
||||
export { shouldLookupName, shouldReuseLocalName, reuseDepName, shouldBeElided };
|
||||
>shouldLookupName : Symbol(shouldLookupName, Decl(index.d.ts, 14, 8))
|
||||
>shouldReuseLocalName : Symbol(shouldReuseLocalName, Decl(index.d.ts, 14, 26))
|
||||
>reuseDepName : Symbol(reuseDepName, Decl(index.d.ts, 14, 48))
|
||||
>shouldBeElided : Symbol(shouldBeElided, Decl(index.d.ts, 14, 62))
|
||||
|
||||
=== src/index.ts ===
|
||||
import { goodDeclaration, shouldReuseLocalName, shouldBeElided } from "some-dep";
|
||||
>goodDeclaration : Symbol(goodDeclaration, Decl(index.ts, 0, 8))
|
||||
>shouldReuseLocalName : Symbol(shouldReuseLocalName, Decl(index.ts, 0, 25))
|
||||
>shouldBeElided : Symbol(shouldBeElided, Decl(index.ts, 0, 47))
|
||||
|
||||
export const bar = goodDeclaration<{}>;
|
||||
>bar : Symbol(bar, Decl(index.ts, 1, 12))
|
||||
>goodDeclaration : Symbol(goodDeclaration, Decl(index.ts, 0, 8))
|
||||
|
||||
|
||||
115
tests/baselines/reference/declarationEmitUsingTypeAlias2.types
Normal file
115
tests/baselines/reference/declarationEmitUsingTypeAlias2.types
Normal file
@@ -0,0 +1,115 @@
|
||||
//// [tests/cases/compiler/declarationEmitUsingTypeAlias2.ts] ////
|
||||
|
||||
=== node_modules/some-dep/dist/inner.d.ts ===
|
||||
export declare type Other = { other: string };
|
||||
>Other : Other
|
||||
> : ^^^^^
|
||||
>other : string
|
||||
> : ^^^^^^
|
||||
|
||||
export declare type SomeType = { arg: Other };
|
||||
>SomeType : SomeType
|
||||
> : ^^^^^^^^
|
||||
>arg : Other
|
||||
> : ^^^^^
|
||||
|
||||
=== node_modules/some-dep/dist/other.d.ts ===
|
||||
export declare const shouldLookupName: unique symbol;
|
||||
>shouldLookupName : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
export declare const shouldReuseLocalName: unique symbol;
|
||||
>shouldReuseLocalName : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
export declare const reuseDepName: unique symbol;
|
||||
>reuseDepName : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
export declare const shouldBeElided: unique symbol;
|
||||
>shouldBeElided : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
export declare const isNotAccessibleShouldError: unique symbol;
|
||||
>isNotAccessibleShouldError : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
=== node_modules/some-dep/dist/index.d.ts ===
|
||||
import { Other } from './inner'
|
||||
>Other : any
|
||||
> : ^^^
|
||||
|
||||
import { shouldLookupName, reuseDepName, shouldReuseLocalName, shouldBeElided } from './other'
|
||||
>shouldLookupName : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
>reuseDepName : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
>shouldReuseLocalName : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
>shouldBeElided : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
export declare const goodDeclaration: <T>() => () => {
|
||||
>goodDeclaration : <T>() => () => { shouldPrintResult: T extends Other ? "O" : "N"; shouldPrintResult2: T extends typeof shouldBeElided ? Other : "N"; shouldLookupName: typeof import("./other").shouldLookupName; shouldReuseLocalName: typeof shouldReuseLocalName; reuseDepName: typeof reuseDepName; }
|
||||
> : ^ ^^^^^^^
|
||||
|
||||
/** Other Can't be named in index.ts, but the whole conditional type can be resolved */
|
||||
shouldPrintResult: T extends Other? "O": "N",
|
||||
>shouldPrintResult : T extends Other ? "O" : "N"
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
/** Symbol shouldBeElided should not be present in index.d.ts, it might be since it's tracked before Other is seen and an error reported */
|
||||
shouldPrintResult2: T extends typeof shouldBeElided? Other: "N",
|
||||
>shouldPrintResult2 : T extends unique symbol ? Other : "N"
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>shouldBeElided : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
/** Specifier should come from module, local path should not be reused */
|
||||
shouldLookupName: typeof import('./other').shouldLookupName,
|
||||
>shouldLookupName : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
>shouldLookupName : error
|
||||
|
||||
/** This is imported in index so local name should be reused */
|
||||
shouldReuseLocalName: typeof shouldReuseLocalName
|
||||
>shouldReuseLocalName : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
>shouldReuseLocalName : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
/** This is NOT imported in index so import should be created */
|
||||
reuseDepName: typeof reuseDepName,
|
||||
>reuseDepName : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
>reuseDepName : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
}
|
||||
export { shouldLookupName, shouldReuseLocalName, reuseDepName, shouldBeElided };
|
||||
>shouldLookupName : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
>shouldReuseLocalName : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
>reuseDepName : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
>shouldBeElided : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
=== src/index.ts ===
|
||||
import { goodDeclaration, shouldReuseLocalName, shouldBeElided } from "some-dep";
|
||||
>goodDeclaration : <T>() => () => { shouldPrintResult: T extends import("node_modules/some-dep/dist/inner").Other ? "O" : "N"; shouldPrintResult2: T extends typeof shouldBeElided ? import("node_modules/some-dep/dist/inner").Other : "N"; shouldLookupName: typeof import("node_modules/some-dep/dist/other").shouldLookupName; shouldReuseLocalName: typeof shouldReuseLocalName; reuseDepName: typeof import("node_modules/some-dep/dist/other").reuseDepName; }
|
||||
> : ^ ^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^
|
||||
>shouldReuseLocalName : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
>shouldBeElided : unique symbol
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
export const bar = goodDeclaration<{}>;
|
||||
>bar : () => () => { shouldPrintResult: {} extends import("node_modules/some-dep/dist/inner").Other ? "O" : "N"; shouldPrintResult2: {} extends typeof shouldBeElided ? import("node_modules/some-dep/dist/inner").Other : "N"; shouldLookupName: typeof import("node_modules/some-dep/dist/other").shouldLookupName; shouldReuseLocalName: typeof shouldReuseLocalName; reuseDepName: typeof import("node_modules/some-dep/dist/other").reuseDepName; }
|
||||
> : ^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^
|
||||
>goodDeclaration<{}> : () => () => { shouldPrintResult: {} extends import("node_modules/some-dep/dist/inner").Other ? "O" : "N"; shouldPrintResult2: {} extends typeof shouldBeElided ? import("node_modules/some-dep/dist/inner").Other : "N"; shouldLookupName: typeof import("node_modules/some-dep/dist/other").shouldLookupName; shouldReuseLocalName: typeof shouldReuseLocalName; reuseDepName: typeof import("node_modules/some-dep/dist/other").reuseDepName; }
|
||||
> : ^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^
|
||||
>goodDeclaration : <T>() => () => { shouldPrintResult: T extends import("node_modules/some-dep/dist/inner").Other ? "O" : "N"; shouldPrintResult2: T extends typeof shouldBeElided ? import("node_modules/some-dep/dist/inner").Other : "N"; shouldLookupName: typeof import("node_modules/some-dep/dist/other").shouldLookupName; shouldReuseLocalName: typeof shouldReuseLocalName; reuseDepName: typeof import("node_modules/some-dep/dist/other").reuseDepName; }
|
||||
> : ^ ^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^
|
||||
|
||||
|
||||
44
tests/cases/compiler/declarationEmitUsingTypeAlias2.ts
Normal file
44
tests/cases/compiler/declarationEmitUsingTypeAlias2.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
// @strict: true
|
||||
// @declaration: true
|
||||
// @module: nodenext
|
||||
|
||||
// @filename: node_modules/some-dep/dist/inner.d.ts
|
||||
export declare type Other = { other: string };
|
||||
export declare type SomeType = { arg: Other };
|
||||
|
||||
// @filename: node_modules/some-dep/dist/other.d.ts
|
||||
export declare const shouldLookupName: unique symbol;
|
||||
export declare const shouldReuseLocalName: unique symbol;
|
||||
export declare const reuseDepName: unique symbol;
|
||||
export declare const shouldBeElided: unique symbol;
|
||||
export declare const isNotAccessibleShouldError: unique symbol;
|
||||
|
||||
// @filename: node_modules/some-dep/dist/index.d.ts
|
||||
import { Other } from './inner'
|
||||
import { shouldLookupName, reuseDepName, shouldReuseLocalName, shouldBeElided } from './other'
|
||||
export declare const goodDeclaration: <T>() => () => {
|
||||
/** Other Can't be named in index.ts, but the whole conditional type can be resolved */
|
||||
shouldPrintResult: T extends Other? "O": "N",
|
||||
/** Symbol shouldBeElided should not be present in index.d.ts, it might be since it's tracked before Other is seen and an error reported */
|
||||
shouldPrintResult2: T extends typeof shouldBeElided? Other: "N",
|
||||
/** Specifier should come from module, local path should not be reused */
|
||||
shouldLookupName: typeof import('./other').shouldLookupName,
|
||||
/** This is imported in index so local name should be reused */
|
||||
shouldReuseLocalName: typeof shouldReuseLocalName
|
||||
/** This is NOT imported in index so import should be created */
|
||||
reuseDepName: typeof reuseDepName,
|
||||
}
|
||||
export { shouldLookupName, shouldReuseLocalName, reuseDepName, shouldBeElided };
|
||||
|
||||
// @filename: node_modules/some-dep/package.json
|
||||
{
|
||||
"name": "some-dep",
|
||||
"exports": {
|
||||
".": "./dist/index.js"
|
||||
}
|
||||
}
|
||||
|
||||
// @filename: src/index.ts
|
||||
import { goodDeclaration, shouldReuseLocalName, shouldBeElided } from "some-dep";
|
||||
export const bar = goodDeclaration<{}>;
|
||||
|
||||
Reference in New Issue
Block a user