-
Notifications
You must be signed in to change notification settings - Fork 442
Description
🚀 Feature Request: Support multi-schema compilation with cross-file type deduplication (aggregate / project mode)
Summary
json-schema-to-typescript currently treats each schema input as an isolated compilation unit. When multiple schemas reference the same shared definitions (via $ref), generating TypeScript types from each schema independently results in duplicate interface definitions across output files.
This makes it difficult to use the tool for schema-driven contract repositories where:
- Schemas are split across multiple YAML files
- Shared base types (e.g.
BaseEntity) are reused via$ref - Consumers expect a single, canonical TypeScript type identity
Problem Description
Consider a common schema layout:
schemas/
├── common.yaml # BaseEntity, EntityId, shared primitives
├── clinic.yaml
├── clinic.view.yaml
├── clinic.create.yaml
└── clinic.update.yaml
common.yaml defines shared types:
$defs:
BaseEntity:
type: object
properties:
schemaVersion:
type: string
const: "v1"Other schemas reuse it:
allOf:
- $ref: "common.yaml#/$defs/BaseEntity"
- type: object
properties:
id:
type: stringWhen running:
json-schema-to-typescript clinic.yaml --output clinic.ts
json-schema-to-typescript clinic.view.yaml --output clinic.view.tsEach output file redefines BaseEntity, even though the $ref points to the same external definition.
This leads to:
- Duplicate interface definitions
- No shared type identity across files
- Inability to safely compose types in TypeScript
- Broken “single source of truth” contract semantics
This means that json-schema-to-typescript currently has no project-level symbol graph or cross-file reuse model.
Why This Matters (Use Case)
This limitation makes it hard to use json-schema-to-typescript in:
- Domain contract repositories
- Schema-first backend/frontend architectures
- Long-lived systems with versioned schemas
- Migration-aware models (e.g.
schemaVersionfields)
In these setups, shared base types are fundamental, and duplication breaks correctness, not just aesthetics.
Parallel: datamodel-code-generator (Python)
For reference, the Python tool datamodel-code-generator solves this exact problem by supporting:
- Directory-level input
- Model reuse via a shared symbol graph
- Cross-file deduplication
- A single generation pass that produces multiple modules with shared imports
Example flags:
datamodel-codegen \
--input schemas/ \
--reuse-model \
--reuse-scope tree \
--module-split-mode singleThis ensures:
BaseEntityis generated once- Other models import it instead of redefining it
A similar concept (not necessarily identical implementation) would unlock powerful new use cases for json-schema-to-typescript.
Proposed Enhancement (High-Level)
Introduce an optional “aggregate / project mode”, for example:
- A single root schema that references others (explicit aggregation)
- Or a directory-based input mode with a unified symbol table
- Or an option to emit imports instead of inlining shared definitions
Important:
This would be opt-in, preserving the current behavior by default.
Why This Is Not a Workaround Request
This issue is not asking for:
- string-based de-duplication
- cosmetic changes
- relaxed validation
It is about type identity correctness when working with multiple schemas that intentionally share definitions.
Closing Thoughts
json-schema-to-typescript is an excellent tool and works extremely well for single-schema workflows. This feature request is about scaling it to multi-schema, contract-driven systems, where shared identity and reuse are essential.
Happy to help with:
- design discussion
- testing
- documentation
- concrete examples
Thanks for considering!