Summary
Provide first-class TypeScript support by exporting declaration files (.d.ts) for all public classes and APIs (e.g., Repository.d.ts, Field.d.ts, etc.). Because classes and repositories are composed at runtime, introduce a lightweight metadata/registry and a build-time declaration generator that emits .d.ts definitions per file and a bundled types/index.d.ts entry point. This gives consumers accurate autocomplete, type inference, and safety without rewriting the runtime.
Goals
- Export stable
.d.ts for all public classes/types (e.g., Repository, Field, Query, etc.).
- Maintain definitions per source file (e.g.,
src/repository.js → types/Repository.d.ts).
- Support the dynamic/runtime composition model while preserving accurate types in editors.
- Publish
"types": "types/index.d.ts" for out-of-the-box DX.
Non-Goals
- Rewriting runtime to TypeScript.
- Changing public runtime APIs.
Approach
1) Authoritative Type Surface via JSDoc or Handwritten d.ts
- For stable, non-dynamic surfaces (e.g., core class method signatures), add JSDoc types in the source or hand-author slim
.d.ts shims. This lets tsc --emitDeclarationOnly or a bundler (e.g., dts-bundle-generator) produce consistent declarations.
- Example:
types/Repository.d.ts declares constructor and methods that exist at runtime.
2) Dynamic Surfaces via Metadata + Codegen
- Introduce a small runtime-agnostic “descriptor” layer that mirrors how classes/repositories are composed at runtime. Example descriptor:
interface RepoDescriptor {
name: string;
fields: Record<string, "string" | "number" | "boolean" | "date" | "json">;
}
- During the build, a generator script traverses these descriptors (which can be authored, derived, or assembled from runtime composition inputs) and emits strongly-typed
.d.ts interfaces and module augmentations. This preserves autocomplete for per-repo fields and other dynamic additions.
- The generator writes:
- Per-file declarations (e.g.,
types/Repository.d.ts, types/Fields.d.ts).
- A consolidated
types/index.d.ts with re-exports for "types" entry.
3) Packaging
package.json:
"types": "types/index.d.ts"
- Include
"types" directory in files array.
- Add a build step (e.g.,
npm run build:types) that runs the generator before publish.
4) Maintenance Strategy
- Prefer “definition-per-file” so ownership maps to the runtime source files.
- Keep dynamic surfaces strictly driven by descriptors to avoid drift.
- Add CI validation to ensure generator is run and outputs are committed or packaged.
Acceptance Criteria
- Consumers get autocomplete for repository instances and their fields (e.g.,
repo.get("username") infers string).
types/ contains one .d.ts per public module plus index.d.ts.
package.json exposes "types": "types/index.d.ts".
- Demo project compiles and shows autocomplete without needing the source code.
Alternatives Considered
- Full TS rewrite: too invasive for current goals.
- Pure JSDoc without codegen: insufficient for highly dynamic composition.
Demo
A minimal demo is included to show how a consumer receives autocomplete from exported .d.ts files, including dynamically-described repository fields.
Summary
Provide first-class TypeScript support by exporting declaration files (
.d.ts) for all public classes and APIs (e.g.,Repository.d.ts,Field.d.ts, etc.). Because classes and repositories are composed at runtime, introduce a lightweight metadata/registry and a build-time declaration generator that emits.d.tsdefinitions per file and a bundledtypes/index.d.tsentry point. This gives consumers accurate autocomplete, type inference, and safety without rewriting the runtime.Goals
.d.tsfor all public classes/types (e.g., Repository, Field, Query, etc.).src/repository.js→types/Repository.d.ts)."types": "types/index.d.ts"for out-of-the-box DX.Non-Goals
Approach
1) Authoritative Type Surface via JSDoc or Handwritten d.ts
.d.tsshims. This letstsc --emitDeclarationOnlyor a bundler (e.g.,dts-bundle-generator) produce consistent declarations.types/Repository.d.tsdeclares constructor and methods that exist at runtime.2) Dynamic Surfaces via Metadata + Codegen
.d.tsinterfaces and module augmentations. This preserves autocomplete for per-repo fields and other dynamic additions.types/Repository.d.ts,types/Fields.d.ts).types/index.d.tswith re-exports for"types"entry.3) Packaging
package.json:"types": "types/index.d.ts""types"directory infilesarray.npm run build:types) that runs the generator before publish.4) Maintenance Strategy
Acceptance Criteria
repo.get("username")infersstring).types/contains one.d.tsper public module plusindex.d.ts.package.jsonexposes"types": "types/index.d.ts".Alternatives Considered
Demo
A minimal demo is included to show how a consumer receives autocomplete from exported
.d.tsfiles, including dynamically-described repository fields.