Based on information from microsoft/TypeScript#54630, particularly highlighted in this statement by the TS team dev lead:
No definitive assurances exist regarding the behavior when an error type is present in your program.
If you attempt to import something that cannot be located, a compiler error will occur:
import { A } from "https://example.com/type.d.ts"; // error!
// -------------> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Cannot find module 'https://example.com/type.d.ts' or its corresponding type declarations.
The references to the missing item may be displayed as the any
type, due to various reasons.
The hover displays "any" as there is no better alternative at hand. While differentiation is conceivable, such details tend not to persist in programs for extended periods.
This clarifies why instances of any
are observed sometimes.
Regarding the display of A
rather than any
after transition from
type B = A | A
// ^? type B = any
to
type C = A;
// ^? type C = A
no consistent and documented rule governs how these types are exhibited. If A
occasionally appears as any
, it falls under the discretion of the compiler to determine the presentation. Even without errors, this dichotomy would still arise:
type D = { a: string };
type E = D;
// ^? type E = { a: string; }
type F = D[];
// ^? type F = D[];
Here, type D
serves as an obvious alias for {a: string}
. Certain uses of D
resolve to {a: string}
, while some retain the alias itself.
These distinctions concern solely the visual representation of the type, without impacting the underlying nature of the identities. Presently, developers lack a supported method to dictate the preferred appearance of a type when displayed. Several open feature requests like microsoft/TypeScript#28508, microsoft/TypeScript#31940, and microsoft/TypeScript#45954 could potentially alter this scenario, but currently, it is not inherent to the language. The compiler employs heuristics to determine the type for display; although effective in diverse scenarios, they cannot cater to all requirements simultaneously. For every individual preferring D
to show as {a: string}
, there exists an opposing viewpoint advocating for maintaining it as D
, both with valid reasoning, perceiving their preference as enhancing consistency. More control over this aspect by developers would be advantageous; lacking that, the outcome remains unpredictable.
Hence, with regards to the discrepancy between seeing any
for A | A
but A
for A
, pinpointing a specific reason entails delving into TypeScript compiler code alongside documentation detailing the accountable components. However, such insights may not yield significant revelations, subject to alterations in future TypeScript versions. When two types are identical, the compiler retains complete authority over determining which manifestation to exhibit and when.
Access the Playground link for the code snippet