Hone logo
Hone
Problems

Monorepo Type System Generator

Building and maintaining large TypeScript projects often involves multiple packages sharing common types and interfaces. A monorepo architecture, where multiple packages reside within a single repository, amplifies this need for shared type definitions. This challenge asks you to create a utility that generates a simplified type definition file (shared.d.ts) from a list of package names, inferring common types based on a provided set of interfaces.

Problem Description

You are tasked with creating a TypeScript function generateSharedTypes that takes an array of package names and an object containing interface definitions as input. The function should analyze the provided interfaces and generate a shared.d.ts file content string. This file will contain a merged declaration of all interfaces, ensuring type safety across the monorepo.

What needs to be achieved:

  • Parse a list of package names.
  • Analyze a provided object of interface definitions.
  • Generate a shared.d.ts file content string containing merged interface declarations.
  • Handle potential naming conflicts gracefully (e.g., by prefixing conflicting interface names with the package name).

Key Requirements:

  • The generated shared.d.ts file should be valid TypeScript.
  • All interfaces provided in the input object should be included in the output.
  • If multiple interfaces have the same name, the function should prefix the conflicting interfaces with the package name that owns them to avoid errors.
  • The function should be robust and handle edge cases such as empty input arrays or empty interface objects.

Expected Behavior:

The function should return a string representing the content of the shared.d.ts file. This string should contain the merged interface declarations, properly formatted and ready to be written to a file.

Edge Cases to Consider:

  • Empty package name array.
  • Empty interface object.
  • Multiple interfaces with the same name originating from different packages.
  • Complex interface structures (nested interfaces, unions, intersections).
  • Invalid interface definitions (though the function doesn't need to validate the interfaces, it should handle them gracefully without crashing).

Examples

Example 1:

Input: packageNames = ["packageA", "packageB"], interfaces = {
  "packageA": {
    "User": { id: number, name: string }
  },
  "packageB": {
    "User": { email: string, isAdmin: boolean }
  }
}
Output:
```typescript
// shared.d.ts
interface packageAUser {
  id: number;
  name: string;
}

interface packageBUser {
  email: string;
  isAdmin: boolean;
}

Explanation: Two interfaces named "User" exist, one from "packageA" and one from "packageB". They are both included in the output, prefixed with their respective package names.

Example 2:

Input: packageNames = ["packageC"], interfaces = {
  "packageC": {
    "Product": {
      id: string;
      price: number;
      description: string;
    }
  }
}
Output:
```typescript
// shared.d.ts
interface packageCProduct {
  id: string;
  price: number;
  description: string;
}

Explanation: A single interface "Product" exists within "packageC". It is included in the output, prefixed with "packageC".

Example 3: (Edge Case)

Input: packageNames = [], interfaces = {}
Output:
```typescript
// shared.d.ts

Explanation: Both the package names array and the interfaces object are empty. The output is an empty file.

Constraints

  • packageNames is an array of strings, each representing a package name.
  • interfaces is an object where keys are package names (matching those in packageNames) and values are objects containing interface definitions. Interface definitions are standard TypeScript interface objects.
  • Package names are non-empty strings.
  • The generated shared.d.ts file content string should be a valid TypeScript declaration file.
  • The function should complete within a reasonable time (e.g., less than 1 second) for a monorepo with up to 100 packages and 50 interfaces per package.

Notes

  • Consider using template literals to construct the shared.d.ts file content string.
  • Pay close attention to the naming conventions and how to handle naming conflicts.
  • The focus is on generating the content of the file, not writing it to disk.
  • You don't need to implement any sophisticated type inference or merging beyond simply concatenating the interface declarations. The goal is to create a basic, functional type system generator.
  • Error handling is not required; assume the input is well-formed.
Loading editor...
typescript