declaration-helpers.ts

Utility functions for working with declaration and member types.

Display formatting, code generation, serialization, type narrowing, and type reference discovery for DeclarationJson and MemberJson.

@see types.ts for DeclarationJson, MemberJson Zod schemas

Declarations
#

6 declarations

view source

buildTypeReferencePatterns
#

declaration-helpers.ts view source

(declarationNames: ReadonlySet<string>): [string, RegExp][]

Pre-compile identifier-boundary patterns for a set of declaration names.

When scanning many type strings against the same declaration set, call this once and pass the result to findTypeReferences to avoid recompiling regexes on every call.

declarationNames

set of known in-project declaration names

type ReadonlySet<string>

returns

[string, RegExp][]

array of [name, pattern] pairs for use with findTypeReferences

examples

const names = new Set(modules.flatMap(m => m.declarations.map(d => d.name))); const patterns = buildTypeReferencePatterns(names); for (const decl of declarations) { const refs = findTypeReferences(decl.typeSignature, patterns); }

compactReplacer
#

declaration-helpers.ts view source

(_key: string, value: unknown): unknown

JSON replacer that strips Zod default values for compact serialization.

Strips empty arrays and false booleans — both are Zod .default() values restored on .parse(), so the round-trip is lossless for svelte-docinfo types. Assumes all boolean fields in the schema default to false — a true-defaulted boolean would need its false values preserved, breaking the round-trip.

Root-value caveat: JSON.stringify([], compactReplacer) returns the JS undefined (not the string '[]'), and JSON.stringify(false, compactReplacer) returns the JS undefined too. Object-rooted callers (AnalyzeResultJson envelope, CLI output) don't hit this — empty inner arrays strip and AnalyzeResultJson.parse restores them on the consumer side. Array-rooted callers (Vite plugin, anyone splicing the JSON into a source template) must handle the empty case themselves before calling this; see vite.ts:updateOutputFromQuery for the pattern.

Two guard tests in declaration-helpers.test.ts lock this in: - every z.boolean().default in types.ts uses false — source-regex check that fails on a new z.boolean().default(true). - `parse → stringify(compactReplacer) → parse is a faithful round-trip across every variant` — exercises every variant and member through a full round-trip, catching regressions where a .default(false) or .default([]) is removed (or a new field is added that the replacer drops but Zod doesn't restore).

_key

type string

value

type unknown

returns

unknown

examples

const result = await analyze({sourceFiles, sourceOptions}); const json = JSON.stringify(result, compactReplacer); // On the consumer side, restore Zod defaults: const restored = AnalyzeResultJson.parse(JSON.parse(json));

findTypeReferences
#

declaration-helpers.ts view source

(typeString: string, declarationNames: ReadonlySet<string> | [string, RegExp][]): string[]

Find in-project declaration names referenced in a type string.

Uses identifier-boundary matching to find which known declaration names appear in an opaque type string (e.g., typeSignature, returnType, parameter type). Enables consumers to render clickable type links without needing access to the TypeScript type checker.

Handles identifiers starting with $ (e.g., $state) which \b does not recognize as word boundaries.

Accepts either a ReadonlySet<string> (convenience) or pre-compiled patterns from buildTypeReferencePatterns (performance). Use pre-compiled patterns when scanning many type strings against the same declaration set.

Known limitations: Identifier-boundary matching can produce false positives when a declaration name appears as a property key in an object literal type (e.g., { Foo: string } when Foo is a declaration). This is rare in practice.

typeString

opaque type string from analysis output

type string

declarationNames

set of names or pre-compiled patterns from buildTypeReferencePatterns

type ReadonlySet<string> | [string, RegExp][]

returns

string[]

array of declaration names found in the type string

examples

const names = new Set(modules.flatMap(m => m.declarations.map(d => d.name))); findTypeReferences('Map<string, ModuleJson[]>', names) // => ['ModuleJson']

generateImport
#

declaration-helpers.ts view source

(declaration: { kind: "function"; parameters: { name: string; type: string; optional: boolean; rest: boolean; description?: string | undefined; defaultValue?: string | undefined; }[]; overloads: { typeSignature: string; ... 4 more ...; returnDescription?: string | undefined; }[]; ... 16 more ...; sourceLine?: number | undefined; } | ... 7 more ... | { ...; }, modulePath: string, libraryName: string): string

Generate TypeScript import statement for a declaration.

Produces import type for type/interface declarations, import for values.

Default export handling: when declaration.name === 'default', emits import X from '...' with the binding derived by PascalCasing the module path. ('default' is the symbol's actual name in JS — import X from 'mod' is sugar for import {default as X} from 'mod'.)

declaration

the DeclarationJson to generate an import for

type { kind: "function"; parameters: { name: string; type: string; optional: boolean; rest: boolean; description?: string | undefined; defaultValue?: string | undefined; }[]; overloads: { typeSignature: string; ... 4 more ...; returnDescription?: string | undefined; }[]; ... 16 more ...; sourceLine?: number | undefined; ...

modulePath

module path relative to source root (e.g., foo.ts)

type string

libraryName

package name for the import specifier (e.g., @pkg/lib)

type string

returns

string

formatted import statement string

examples

generateImport({name: 'Foo', kind: 'type'}, 'foo.ts', '@pkg/lib') // => "import type {Foo} from '@pkg/lib/foo.js';" generateImport({name: 'default', kind: 'function'}, 'foo-bar.ts', '@pkg/lib') // => "import FooBar from '@pkg/lib/foo-bar.js';"

see also

  • ``getDisplayName`` for the divergent default-slot fallback used as a display label (the literal 'default', since a label has no use for a synthesized JS binding).

getDisplayName
#

declaration-helpers.ts view source

(declaration: { kind: "function"; name: string; optional: boolean; parameters: { name: string; type: string; optional: boolean; rest: boolean; description?: string | undefined; defaultValue?: string | undefined; }[]; ... 14 more ...; sourceLine?: number | undefined; } | ... 10 more ... | { ...; }): string

Format declaration or member name with generic parameters for display.

Default-slot entries return the literal 'default' (the symbol's actual name in JS). Renderers that want a richer label (PascalCased module path, an explicit "default export" header) should branch on name === 'default' themselves before calling this.

declaration

the DeclarationJson or MemberJson to format

type { kind: "function"; name: string; optional: boolean; parameters: { name: string; type: string; optional: boolean; rest: boolean; description?: string | undefined; defaultValue?: string | undefined; }[]; ... 14 more ...; sourceLine?: number | undefined; } | ... 10 more ... | { ...; }

returns

string

name with generic parameters appended (e.g., Map<K, V>)

examples

getDisplayName({name: 'Map', kind: 'type', genericParams: [{name: 'K'}, {name: 'V'}]}) // => 'Map<K, V>'

see also

  • ``generateImport`` for the divergent default-slot fallback used in import-statement generation (PascalCased module path, since an import needs a JS identifier binding, not a label).

isKind
#

declaration-helpers.ts view source

<K extends DeclarationKind | MemberKind>(declaration: { kind: "function"; name: string; optional: boolean; parameters: { name: string; type: string; optional: boolean; rest: boolean; description?: string | undefined; defaultValue?: string | undefined; }[]; ... 14 more ...; sourceLine?: number | undefined; } | ... 10 more ... | { ...; }, kind: K): declaration is Extract<...> | ... 10 more ... | Extract<...>

Narrow a declaration by kind for type-safe field access.

Works with both DeclarationJson (top-level) and MemberJson (nested). Accepts DeclarationKind | MemberKind so isKind(member, 'constructor') compiles.

declaration

type { kind: "function"; name: string; optional: boolean; parameters: { name: string; type: string; optional: boolean; rest: boolean; description?: string | undefined; defaultValue?: string | undefined; }[]; ... 14 more ...; sourceLine?: number | undefined; } | ... 10 more ... | { ...; }

kind

type K

returns

boolean

examples

if (isKind(declaration, 'function')) { declaration.parameters; // FunctionDeclarationJson — has parameters declaration.returnType; // has returnType } if (isKind(member, 'constructor')) { member.parameters; // ConstructorMemberJson — has parameters }

Imported by
#