diff --git a/tsc/internal/checker/nodebuilderimpl.go b/tsc/internal/checker/nodebuilderimpl.go index 128dd968c79e5..1f63b9ee9a5de 100644 --- a/tsc/internal/checker/nodebuilderimpl.go +++ b/tsc/internal/checker/nodebuilderimpl.go @@ -702,45 +702,12 @@ func (b *NodeBuilderImpl) symbolToTypeNode(symbol *ast.Symbol, mask ast.SymbolFl if typeParameterNodes == nil { typeParameterNodes = b.lookupTypeParameterNodes(chain, 0) } - contextFile := ast.GetSourceFileOfNode(b.e.MostOriginal(b.ctx.enclosingDeclaration)) // TODO: Just use b.ctx.enclosingFile ? Or is the delayed lookup important for context moves? - targetFile := ast.GetSourceFileOfModule(chain[0]) - var specifierResult moduleSpecifierResult - var importModeOverride core.ResolutionMode - if b.ch.compilerOptions.GetModuleResolutionKind() == core.ModuleResolutionKindNode16 || b.ch.compilerOptions.GetModuleResolutionKind() == core.ModuleResolutionKindNodeNext { - // An `import` type directed at an esm format file is only going to resolve in esm mode - set the esm mode assertion - if targetFile != nil && contextFile != nil && b.ch.program.GetEmitModuleFormatOfFile(targetFile) == core.ModuleKindESNext && b.ch.program.GetEmitModuleFormatOfFile(targetFile) != b.ch.program.GetEmitModuleFormatOfFile(contextFile) { - specifierResult = b.getSpecifierForModuleSymbol(chain[0], core.ModuleKindESNext) - importModeOverride = core.ModuleKindESNext - } - } - if len(specifierResult.specifier) == 0 { - specifierResult = b.getSpecifierForModuleSymbol(chain[0], core.ResolutionModeNone) - } - if (b.ctx.flags&nodebuilder.FlagsAllowNodeModulesRelativePaths == 0) /* && b.ch.compilerOptions.GetModuleResolutionKind() != core.ModuleResolutionKindClassic */ && strings.Contains(specifierResult.specifier.AsString(), "/node_modules/") { - oldSpecifierResult := specifierResult - - if b.ch.compilerOptions.GetModuleResolutionKind() == core.ModuleResolutionKindNode16 || b.ch.compilerOptions.GetModuleResolutionKind() == core.ModuleResolutionKindNodeNext { - // We might be able to write a portable import type using a mode override; try specifier generation again, but with a different mode set - swappedMode := core.ModuleKindESNext - if b.ch.program.GetEmitModuleFormatOfFile(contextFile) == core.ModuleKindESNext { - swappedMode = core.ModuleKindCommonJS - } - specifierResult = b.getSpecifierForModuleSymbol(chain[0], swappedMode) - - if strings.Contains(specifierResult.specifier.AsString(), "/node_modules/") { - // Still unreachable :( - specifierResult = oldSpecifierResult - } else { - importModeOverride = swappedMode - } - } - - if importModeOverride == core.ResolutionModeNone { - // If ultimately we can only name the symbol with a reference that dives into a `node_modules` folder, we should error - // since declaration files with these kinds of references are liable to fail when published :( - b.ctx.encounteredError = true - b.ctx.tracker.ReportLikelyUnsafeImportRequiredError(oldSpecifierResult.specifier.AsString(), symbol.Name()) - } + specifierResult, importModeOverride, portable := b.getImportTypeSpecifier(chain[0]) + if !portable { + // If ultimately we can only name the symbol with a reference that dives into a `node_modules` folder, we should error + // since declaration files with these kinds of references are liable to fail when published :( + b.ctx.encounteredError = true + b.ctx.tracker.ReportLikelyUnsafeImportRequiredError(specifierResult.specifier.AsString(), symbol.Name()) } attributes := b.createImportAttributesForModuleSpecifier(specifierResult, importModeOverride) @@ -781,6 +748,58 @@ func (b *NodeBuilderImpl) symbolToTypeNode(symbol *ast.Symbol, mask ast.SymbolFl return entityName } +func (b *NodeBuilderImpl) getImportTypeSpecifier(symbol *ast.Symbol) (moduleSpecifierResult, core.ResolutionMode, bool) { + contextFile := ast.GetSourceFileOfNode(b.e.MostOriginal(b.ctx.enclosingDeclaration)) // TODO: Just use b.ctx.enclosingFile ? Or is the delayed lookup important for context moves? + targetFile := ast.GetSourceFileOfModule(symbol) + var specifierResult moduleSpecifierResult + var importModeOverride core.ResolutionMode + resolutionKind := b.ch.compilerOptions.GetModuleResolutionKind() + if resolutionKind == core.ModuleResolutionKindNode16 || resolutionKind == core.ModuleResolutionKindNodeNext { + // An `import` type directed at an esm format file is only going to resolve in esm mode - set the esm mode assertion + if targetFile != nil && contextFile != nil && b.ch.program.GetEmitModuleFormatOfFile(targetFile) == core.ModuleKindESNext && b.ch.program.GetEmitModuleFormatOfFile(targetFile) != b.ch.program.GetEmitModuleFormatOfFile(contextFile) { + specifierResult = b.getSpecifierForModuleSymbol(symbol, core.ModuleKindESNext) + importModeOverride = core.ModuleKindESNext + } + } + if len(specifierResult.specifier) == 0 { + specifierResult = b.getSpecifierForModuleSymbol(symbol, core.ResolutionModeNone) + } + if (b.ctx.flags&nodebuilder.FlagsAllowNodeModulesRelativePaths == 0) /* && b.ch.compilerOptions.GetModuleResolutionKind() != core.ModuleResolutionKindClassic */ && strings.Contains(specifierResult.specifier.AsString(), "/node_modules/") { + oldSpecifierResult := specifierResult + + if resolutionKind == core.ModuleResolutionKindNode16 || resolutionKind == core.ModuleResolutionKindNodeNext { + // We might be able to write a portable import type using a mode override; try specifier generation again, but with a different mode set + swappedMode := core.ModuleKindESNext + if b.ch.program.GetEmitModuleFormatOfFile(contextFile) == core.ModuleKindESNext { + swappedMode = core.ModuleKindCommonJS + } + specifierResult = b.getSpecifierForModuleSymbol(symbol, swappedMode) + + if strings.Contains(specifierResult.specifier.AsString(), "/node_modules/") { + // Still unreachable :( + specifierResult = oldSpecifierResult + } else { + importModeOverride = swappedMode + } + } + return specifierResult, importModeOverride, importModeOverride != core.ResolutionModeNone + } + return specifierResult, importModeOverride, true +} + +func (b *NodeBuilderImpl) shouldExpandUnreachableMappedType(t *Type) bool { + if b.ctx.flags&nodebuilder.FlagsUseStructuralFallback == 0 || + t.objectFlags&ObjectFlagsMapped == 0 || b.ch.isGenericMappedType(t) { + return false + } + chain := b.lookupSymbolChainWorker(t.alias.Symbol(), ast.SymbolFlagsType, b.ctx.flags&nodebuilder.FlagsUseAliasDefinedOutsideCurrentScope == 0) + if !core.Some(chain[0].Declarations(), hasNonGlobalAugmentationExternalModuleSymbol) { + return false + } + _, _, portable := b.getImportTypeSpecifier(chain[0]) + return !portable +} + func getTopmostIndexedAccessType(node *ast.IndexedAccessTypeNode) *ast.IndexedAccessTypeNode { if ast.IsIndexedAccessTypeNode(node.ObjectType) { return getTopmostIndexedAccessType(node.ObjectType.AsIndexedAccessTypeNode()) @@ -3565,7 +3584,8 @@ func (b *NodeBuilderImpl) typeToTypeNode(t *Type) *ast.TypeNode { return b.f.NewThisTypeNode() } - if inTypeAlias == 0 && t.alias != nil && (b.ctx.flags&nodebuilder.FlagsUseAliasDefinedOutsideCurrentScope != 0 || b.ch.IsTypeSymbolAccessible(t.alias.Symbol(), b.ctx.enclosingDeclaration)) { + if inTypeAlias == 0 && t.alias != nil && (b.ctx.flags&nodebuilder.FlagsUseAliasDefinedOutsideCurrentScope != 0 || b.ch.IsTypeSymbolAccessible(t.alias.Symbol(), b.ctx.enclosingDeclaration)) && + !b.shouldExpandUnreachableMappedType(t) { // If we should expand this type alias, skip the alias and fall through to expand the underlying type if !b.shouldExpandType(t, true /*isAlias*/) { return b.serializationTypeNameToNode(serializationTypeName{ diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitObjectAssignedDefaultExport.errors.txt b/tsc/testdata/baselines/reference/compiler/declarationEmitObjectAssignedDefaultExport.errors.txt index 8396aee5921c5..bb2e89196f8ff 100644 --- a/tsc/testdata/baselines/reference/compiler/declarationEmitObjectAssignedDefaultExport.errors.txt +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitObjectAssignedDefaultExport.errors.txt @@ -1,4 +1,4 @@ -index.ts(7,1): error TS2883: The inferred type of 'default' cannot be named without a reference to 'NonReactStatics' from 'styled-components/node_modules/hoist-non-react-statics'. This is likely not portable. A type annotation is necessary. +index.ts(7,1): error TS4118: The type of this node cannot be serialized because its property '[iterator]' cannot be serialized. ==== node_modules/styled-components/node_modules/hoist-non-react-statics/index.d.ts (0 errors) ==== @@ -43,5 +43,5 @@ index.ts(7,1): error TS2883: The inferred type of 'default' cannot be named with ~~~~~ }); ~~~ -!!! error TS2883: The inferred type of 'default' cannot be named without a reference to 'NonReactStatics' from 'styled-components/node_modules/hoist-non-react-statics'. This is likely not portable. A type annotation is necessary. +!!! error TS4118: The type of this node cannot be serialized because its property '[iterator]' cannot be serialized. \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitUsingTypeAlias1.errors.txt b/tsc/testdata/baselines/reference/compiler/declarationEmitUsingTypeAlias1.errors.txt index b243748856549..a4be57afd276e 100644 --- a/tsc/testdata/baselines/reference/compiler/declarationEmitUsingTypeAlias1.errors.txt +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitUsingTypeAlias1.errors.txt @@ -1,3 +1,4 @@ +src/genericMapped.ts(3,14): error TS2883: The inferred type of 'generic' cannot be named without a reference to '_HelperObjectDeep' from '../node_modules/deep-types/source'. This is likely not portable. A type annotation is necessary. src/index.ts(3,14): error TS2883: The inferred type of 'foo' cannot be named without a reference to 'SomeType' from '../node_modules/some-dep/dist/inner'. This is likely not portable. A type annotation is necessary. src/index.ts(7,14): error TS2883: The inferred type of 'bar' cannot be named without a reference to 'Other' from '../node_modules/some-dep/dist/inner'. This is likely not portable. A type annotation is necessary. @@ -31,4 +32,43 @@ src/index.ts(7,14): error TS2883: The inferred type of 'bar' cannot be named wit ~~~ !!! error TS2883: The inferred type of 'bar' cannot be named without a reference to 'Other' from '../node_modules/some-dep/dist/inner'. This is likely not portable. A type annotation is necessary. return thing.arg; - }; \ No newline at end of file + }; + +==== node_modules/deep-types/package.json (0 errors) ==== + { + "name": "deep-types", + "exports": { + ".": { "types": "./index.d.ts" } + } + } + +==== node_modules/deep-types/index.d.ts (0 errors) ==== + export type { HelperDeep, InlineDeep, PublicMapped } from "./source.js"; + export { mapped } from "./source.js"; + +==== node_modules/deep-types/source.d.ts (0 errors) ==== + export type HelperDeep = T extends object ? _HelperObjectDeep : T; + export type _HelperObjectDeep = { readonly [K in keyof T]: HelperDeep }; + export type InlineDeep = T extends object ? { readonly [K in keyof T]: InlineDeep } : T; + export type PublicMapped = { readonly [K in keyof T]: T[K] }; + export declare function mapped(value: T): _HelperObjectDeep; + +==== src/mapped.ts (0 errors) ==== + import type { HelperDeep, InlineDeep, PublicMapped } from "deep-types"; + + type Tree = { value: string; children: Tree[] }; + declare function helper(value: T): HelperDeep; + declare function inline(value: T): InlineDeep; + declare function publicMapped(value: T): PublicMapped; + + export const recursive = helper({} as Tree); + export const finite = helper({ value: "text" }); + export const inlined = inline({} as Tree); + export const named = publicMapped({ value: "text" }); + +==== src/genericMapped.ts (1 errors) ==== + import { mapped } from "deep-types"; + + export const generic = (value: T) => mapped(value); + ~~~~~~~ +!!! error TS2883: The inferred type of 'generic' cannot be named without a reference to '_HelperObjectDeep' from '../node_modules/deep-types/source'. This is likely not portable. A type annotation is necessary. \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitUsingTypeAlias1.js b/tsc/testdata/baselines/reference/compiler/declarationEmitUsingTypeAlias1.js index c243d425a035e..ec86238eb29cc 100644 --- a/tsc/testdata/baselines/reference/compiler/declarationEmitUsingTypeAlias1.js +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitUsingTypeAlias1.js @@ -25,7 +25,44 @@ export const foo = (thing: SomeType) => { export const bar = (thing: SomeType) => { return thing.arg; -}; +}; + +//// [package.json] +{ + "name": "deep-types", + "exports": { + ".": { "types": "./index.d.ts" } + } +} + +//// [index.d.ts] +export type { HelperDeep, InlineDeep, PublicMapped } from "./source.js"; +export { mapped } from "./source.js"; + +//// [source.d.ts] +export type HelperDeep = T extends object ? _HelperObjectDeep : T; +export type _HelperObjectDeep = { readonly [K in keyof T]: HelperDeep }; +export type InlineDeep = T extends object ? { readonly [K in keyof T]: InlineDeep } : T; +export type PublicMapped = { readonly [K in keyof T]: T[K] }; +export declare function mapped(value: T): _HelperObjectDeep; + +//// [mapped.ts] +import type { HelperDeep, InlineDeep, PublicMapped } from "deep-types"; + +type Tree = { value: string; children: Tree[] }; +declare function helper(value: T): HelperDeep; +declare function inline(value: T): InlineDeep; +declare function publicMapped(value: T): PublicMapped; + +export const recursive = helper({} as Tree); +export const finite = helper({ value: "text" }); +export const inlined = inline({} as Tree); +export const named = publicMapped({ value: "text" }); + +//// [genericMapped.ts] +import { mapped } from "deep-types"; + +export const generic = (value: T) => mapped(value); //// [index.js] "use strict"; @@ -39,3 +76,36 @@ const bar = (thing) => { return thing.arg; }; exports.bar = bar; +//// [mapped.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.named = exports.inlined = exports.finite = exports.recursive = void 0; +exports.recursive = helper({}); +exports.finite = helper({ value: "text" }); +exports.inlined = inline({}); +exports.named = publicMapped({ value: "text" }); +//// [genericMapped.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.generic = void 0; +const deep_types_1 = require("deep-types"); +const generic = (value) => (0, deep_types_1.mapped)(value); +exports.generic = generic; + + +//// [mapped.d.ts] +import type { PublicMapped } from "deep-types"; +export declare const recursive: { + readonly value: string; + readonly children: readonly (typeof recursive)[]; +}; +export declare const finite: { + readonly value: string; +}; +export declare const inlined: { + readonly value: string; + readonly children: readonly (typeof inlined)[]; +}; +export declare const named: PublicMapped<{ + value: string; +}>; diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitUsingTypeAlias1.symbols b/tsc/testdata/baselines/reference/compiler/declarationEmitUsingTypeAlias1.symbols index 55573f5c9aff2..187ac75d5e9f1 100644 --- a/tsc/testdata/baselines/reference/compiler/declarationEmitUsingTypeAlias1.symbols +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitUsingTypeAlias1.symbols @@ -44,3 +44,126 @@ export const bar = (thing: SomeType) => { >arg : Symbol(arg, Decl(inner.d.ts, 1, 32)) }; + +=== node_modules/deep-types/index.d.ts === +export type { HelperDeep, InlineDeep, PublicMapped } from "./source.js"; +>HelperDeep : Symbol(HelperDeep, Decl(index.d.ts, 0, 13)) +>InlineDeep : Symbol(InlineDeep, Decl(index.d.ts, 0, 25)) +>PublicMapped : Symbol(PublicMapped, Decl(index.d.ts, 0, 37)) + +export { mapped } from "./source.js"; +>mapped : Symbol(mapped, Decl(index.d.ts, 1, 8)) + +=== node_modules/deep-types/source.d.ts === +export type HelperDeep = T extends object ? _HelperObjectDeep : T; +>HelperDeep : Symbol(HelperDeep, Decl(source.d.ts, 0, 0)) +>T : Symbol(T, Decl(source.d.ts, 0, 23)) +>T : Symbol(T, Decl(source.d.ts, 0, 23)) +>_HelperObjectDeep : Symbol(_HelperObjectDeep, Decl(source.d.ts, 0, 72)) +>T : Symbol(T, Decl(source.d.ts, 0, 23)) +>T : Symbol(T, Decl(source.d.ts, 0, 23)) + +export type _HelperObjectDeep = { readonly [K in keyof T]: HelperDeep }; +>_HelperObjectDeep : Symbol(_HelperObjectDeep, Decl(source.d.ts, 0, 72)) +>T : Symbol(T, Decl(source.d.ts, 1, 30)) +>K : Symbol(K, Decl(source.d.ts, 1, 47)) +>T : Symbol(T, Decl(source.d.ts, 1, 30)) +>HelperDeep : Symbol(HelperDeep, Decl(source.d.ts, 0, 0)) +>T : Symbol(T, Decl(source.d.ts, 1, 30)) +>K : Symbol(K, Decl(source.d.ts, 1, 47)) + +export type InlineDeep = T extends object ? { readonly [K in keyof T]: InlineDeep } : T; +>InlineDeep : Symbol(InlineDeep, Decl(source.d.ts, 1, 81)) +>T : Symbol(T, Decl(source.d.ts, 2, 23)) +>T : Symbol(T, Decl(source.d.ts, 2, 23)) +>K : Symbol(K, Decl(source.d.ts, 2, 59)) +>T : Symbol(T, Decl(source.d.ts, 2, 23)) +>InlineDeep : Symbol(InlineDeep, Decl(source.d.ts, 1, 81)) +>T : Symbol(T, Decl(source.d.ts, 2, 23)) +>K : Symbol(K, Decl(source.d.ts, 2, 59)) +>T : Symbol(T, Decl(source.d.ts, 2, 23)) + +export type PublicMapped = { readonly [K in keyof T]: T[K] }; +>PublicMapped : Symbol(PublicMapped, Decl(source.d.ts, 2, 97)) +>T : Symbol(T, Decl(source.d.ts, 3, 25)) +>K : Symbol(K, Decl(source.d.ts, 3, 42)) +>T : Symbol(T, Decl(source.d.ts, 3, 25)) +>T : Symbol(T, Decl(source.d.ts, 3, 25)) +>K : Symbol(K, Decl(source.d.ts, 3, 42)) + +export declare function mapped(value: T): _HelperObjectDeep; +>mapped : Symbol(mapped, Decl(source.d.ts, 3, 64)) +>T : Symbol(T, Decl(source.d.ts, 4, 31)) +>value : Symbol(value, Decl(source.d.ts, 4, 34)) +>T : Symbol(T, Decl(source.d.ts, 4, 31)) +>_HelperObjectDeep : Symbol(_HelperObjectDeep, Decl(source.d.ts, 0, 72)) +>T : Symbol(T, Decl(source.d.ts, 4, 31)) + +=== src/mapped.ts === +import type { HelperDeep, InlineDeep, PublicMapped } from "deep-types"; +>HelperDeep : Symbol(HelperDeep, Decl(mapped.ts, 0, 13)) +>InlineDeep : Symbol(InlineDeep, Decl(mapped.ts, 0, 25)) +>PublicMapped : Symbol(PublicMapped, Decl(mapped.ts, 0, 37)) + +type Tree = { value: string; children: Tree[] }; +>Tree : Symbol(Tree, Decl(mapped.ts, 0, 71)) +>value : Symbol(value, Decl(mapped.ts, 2, 13)) +>children : Symbol(children, Decl(mapped.ts, 2, 28)) +>Tree : Symbol(Tree, Decl(mapped.ts, 0, 71)) + +declare function helper(value: T): HelperDeep; +>helper : Symbol(helper, Decl(mapped.ts, 2, 48)) +>T : Symbol(T, Decl(mapped.ts, 3, 24)) +>value : Symbol(value, Decl(mapped.ts, 3, 27)) +>T : Symbol(T, Decl(mapped.ts, 3, 24)) +>HelperDeep : Symbol(HelperDeep, Decl(mapped.ts, 0, 13)) +>T : Symbol(T, Decl(mapped.ts, 3, 24)) + +declare function inline(value: T): InlineDeep; +>inline : Symbol(inline, Decl(mapped.ts, 3, 52)) +>T : Symbol(T, Decl(mapped.ts, 4, 24)) +>value : Symbol(value, Decl(mapped.ts, 4, 27)) +>T : Symbol(T, Decl(mapped.ts, 4, 24)) +>InlineDeep : Symbol(InlineDeep, Decl(mapped.ts, 0, 25)) +>T : Symbol(T, Decl(mapped.ts, 4, 24)) + +declare function publicMapped(value: T): PublicMapped; +>publicMapped : Symbol(publicMapped, Decl(mapped.ts, 4, 52)) +>T : Symbol(T, Decl(mapped.ts, 5, 30)) +>value : Symbol(value, Decl(mapped.ts, 5, 33)) +>T : Symbol(T, Decl(mapped.ts, 5, 30)) +>PublicMapped : Symbol(PublicMapped, Decl(mapped.ts, 0, 37)) +>T : Symbol(T, Decl(mapped.ts, 5, 30)) + +export const recursive = helper({} as Tree); +>recursive : Symbol(recursive, Decl(mapped.ts, 7, 12)) +>helper : Symbol(helper, Decl(mapped.ts, 2, 48)) +>Tree : Symbol(Tree, Decl(mapped.ts, 0, 71)) + +export const finite = helper({ value: "text" }); +>finite : Symbol(finite, Decl(mapped.ts, 8, 12)) +>helper : Symbol(helper, Decl(mapped.ts, 2, 48)) +>value : Symbol(value, Decl(mapped.ts, 8, 30)) + +export const inlined = inline({} as Tree); +>inlined : Symbol(inlined, Decl(mapped.ts, 9, 12)) +>inline : Symbol(inline, Decl(mapped.ts, 3, 52)) +>Tree : Symbol(Tree, Decl(mapped.ts, 0, 71)) + +export const named = publicMapped({ value: "text" }); +>named : Symbol(named, Decl(mapped.ts, 10, 12)) +>publicMapped : Symbol(publicMapped, Decl(mapped.ts, 4, 52)) +>value : Symbol(value, Decl(mapped.ts, 10, 35)) + +=== src/genericMapped.ts === +import { mapped } from "deep-types"; +>mapped : Symbol(mapped, Decl(genericMapped.ts, 0, 8)) + +export const generic = (value: T) => mapped(value); +>generic : Symbol(generic, Decl(genericMapped.ts, 2, 12)) +>T : Symbol(T, Decl(genericMapped.ts, 2, 24)) +>value : Symbol(value, Decl(genericMapped.ts, 2, 27)) +>T : Symbol(T, Decl(genericMapped.ts, 2, 24)) +>mapped : Symbol(mapped, Decl(genericMapped.ts, 0, 8)) +>value : Symbol(value, Decl(genericMapped.ts, 2, 27)) + diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitUsingTypeAlias1.types b/tsc/testdata/baselines/reference/compiler/declarationEmitUsingTypeAlias1.types index e11ca9402f6c5..2243ed850506d 100644 --- a/tsc/testdata/baselines/reference/compiler/declarationEmitUsingTypeAlias1.types +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitUsingTypeAlias1.types @@ -41,3 +41,95 @@ export const bar = (thing: SomeType) => { >arg : import("../node_modules/some-dep/dist/inner").Other }; + +=== node_modules/deep-types/index.d.ts === +export type { HelperDeep, InlineDeep, PublicMapped } from "./source.js"; +>HelperDeep : import("./source.js").HelperDeep +>InlineDeep : import("./source.js").InlineDeep +>PublicMapped : import("./source.js").PublicMapped + +export { mapped } from "./source.js"; +>mapped : (value: T) => import("./source.js")._HelperObjectDeep + +=== node_modules/deep-types/source.d.ts === +export type HelperDeep = T extends object ? _HelperObjectDeep : T; +>HelperDeep : HelperDeep + +export type _HelperObjectDeep = { readonly [K in keyof T]: HelperDeep }; +>_HelperObjectDeep : _HelperObjectDeep + +export type InlineDeep = T extends object ? { readonly [K in keyof T]: InlineDeep } : T; +>InlineDeep : InlineDeep + +export type PublicMapped = { readonly [K in keyof T]: T[K] }; +>PublicMapped : PublicMapped + +export declare function mapped(value: T): _HelperObjectDeep; +>mapped : (value: T) => _HelperObjectDeep +>value : T + +=== src/mapped.ts === +import type { HelperDeep, InlineDeep, PublicMapped } from "deep-types"; +>HelperDeep : HelperDeep +>InlineDeep : InlineDeep +>PublicMapped : PublicMapped + +type Tree = { value: string; children: Tree[] }; +>Tree : Tree +>value : string +>children : Tree[] + +declare function helper(value: T): HelperDeep; +>helper : (value: T) => HelperDeep +>value : T + +declare function inline(value: T): InlineDeep; +>inline : (value: T) => InlineDeep +>value : T + +declare function publicMapped(value: T): PublicMapped; +>publicMapped : (value: T) => PublicMapped +>value : T + +export const recursive = helper({} as Tree); +>recursive : import("../node_modules/deep-types/source")._HelperObjectDeep +>helper({} as Tree) : import("../node_modules/deep-types/source")._HelperObjectDeep +>helper : (value: T) => HelperDeep +>{} as Tree : Tree +>{} : {} + +export const finite = helper({ value: "text" }); +>finite : import("../node_modules/deep-types/source")._HelperObjectDeep<{ value: string; }> +>helper({ value: "text" }) : import("../node_modules/deep-types/source")._HelperObjectDeep<{ value: string; }> +>helper : (value: T) => HelperDeep +>{ value: "text" } : { value: string; } +>value : string +>"text" : "text" + +export const inlined = inline({} as Tree); +>inlined : { readonly value: string; readonly children: readonly any[]; } +>inline({} as Tree) : { readonly value: string; readonly children: readonly any[]; } +>inline : (value: T) => InlineDeep +>{} as Tree : Tree +>{} : {} + +export const named = publicMapped({ value: "text" }); +>named : PublicMapped<{ value: string; }> +>publicMapped({ value: "text" }) : PublicMapped<{ value: string; }> +>publicMapped : (value: T) => PublicMapped +>{ value: "text" } : { value: string; } +>value : string +>"text" : "text" + +=== src/genericMapped.ts === +import { mapped } from "deep-types"; +>mapped : (value: T) => import("../node_modules/deep-types/source")._HelperObjectDeep + +export const generic = (value: T) => mapped(value); +>generic : (value: T) => import("../node_modules/deep-types/source")._HelperObjectDeep +>(value: T) => mapped(value) : (value: T) => import("../node_modules/deep-types/source")._HelperObjectDeep +>value : T +>mapped(value) : import("../node_modules/deep-types/source")._HelperObjectDeep +>mapped : (value: T_1) => import("../node_modules/deep-types/source")._HelperObjectDeep +>value : T + diff --git a/tsc/testdata/tests/cases/compiler/declarationEmitUsingTypeAlias1.ts b/tsc/testdata/tests/cases/compiler/declarationEmitUsingTypeAlias1.ts index fddae5fc65df2..380b92c879a64 100644 --- a/tsc/testdata/tests/cases/compiler/declarationEmitUsingTypeAlias1.ts +++ b/tsc/testdata/tests/cases/compiler/declarationEmitUsingTypeAlias1.ts @@ -28,4 +28,41 @@ export const foo = (thing: SomeType) => { export const bar = (thing: SomeType) => { return thing.arg; -}; \ No newline at end of file +}; + +// @filename: node_modules/deep-types/package.json +{ + "name": "deep-types", + "exports": { + ".": { "types": "./index.d.ts" } + } +} + +// @filename: node_modules/deep-types/index.d.ts +export type { HelperDeep, InlineDeep, PublicMapped } from "./source.js"; +export { mapped } from "./source.js"; + +// @filename: node_modules/deep-types/source.d.ts +export type HelperDeep = T extends object ? _HelperObjectDeep : T; +export type _HelperObjectDeep = { readonly [K in keyof T]: HelperDeep }; +export type InlineDeep = T extends object ? { readonly [K in keyof T]: InlineDeep } : T; +export type PublicMapped = { readonly [K in keyof T]: T[K] }; +export declare function mapped(value: T): _HelperObjectDeep; + +// @filename: src/mapped.ts +import type { HelperDeep, InlineDeep, PublicMapped } from "deep-types"; + +type Tree = { value: string; children: Tree[] }; +declare function helper(value: T): HelperDeep; +declare function inline(value: T): InlineDeep; +declare function publicMapped(value: T): PublicMapped; + +export const recursive = helper({} as Tree); +export const finite = helper({ value: "text" }); +export const inlined = inline({} as Tree); +export const named = publicMapped({ value: "text" }); + +// @filename: src/genericMapped.ts +import { mapped } from "deep-types"; + +export const generic = (value: T) => mapped(value); \ No newline at end of file