glideapps / glideapps/quicktype

[BUG]: It's merging types that are not the same

Open
#3,116 2 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
TypeScript
Stars
13.9k
Forks
1.2k
Avg merge
8h 53m
Merged PRs (30d)
369

Description

Types that are "similar" I guess, but not quite the same, are being merged, leading to weird optional properties in the resulting types, where they should not be.

## Issue Type

output

## Context (Environment, Version, Language)

Input Format: json
Output Language: typescript

CLI, npm, or app.quicktype.io: npm & app
Version: 26.0.0

## Description

I'm using it to generate types for strong-typed translation keys. And this bug is breaking that.

## Input Data

```json
{
"User": {
"Profile": {
"Title": "Mijn profiel",
"Error": "Serverfout, probeer het nog een keer",
"Success": "Profiel succesvol bijgewerkt",
"Submit": "Wijzig gegevens",
"Fields": {
"Email": "E-mailadres",
"FirstName": "Voornaam",
"LastName": "Achternaam"
}
},
"ChangePassword": {
"Title": "Wachtwoord wijzigen",
"Error": "Wachtwoord wijzigen is mislukt. Probeer het later nog eens.",
"Success": "Wachtwoord is gewijzigd. De volgende dat u inlogt, kunt u uw nieuwe wachtwoord gebruiken.",
"Submit": "Wijzig wachtwoord",
"Fields": {
"OldPassword": "Huidig wachtwoord",
"NewPassword": "Nieuw wachtwoord",
"ConfirmPassword": "Herhaal wachtwoord ter bevestiging"
}
},
"Notifications": {
"Title": "Notificatievoorkeuren",
"Error": "Notificatievoorkeuren konden niet worden bewaard. Probeer het later nog eens.",
"Success": "Notificatievoorkeuren zijn bewaard.",
"Submit": "Voorkeuren bewaren"
}
}
}
```

## Expected Behaviour / Output

Do not merge types that are mergeable, so it should become something like:

```typescript
export type Welcome = {
User: User;
}

export type User = {
Profile: Profile;
ChangePassword: ChangePassword;
Notifications: Notifications;
}

export type Profile = {
Title: string;
Error: string;
Success: string;
Submit: string;
Fields: ProfileFields;
}

export type Notifications = {
Title: string;
Error: string;
Success: string;
Submit: string;
}

export type Profile = {
Title: string;
Error: string;
Success: string;
Submit: string;
Fields: ProfileFields;
}

export type ProfileFields = {
Email: string;
FirstName: string;
LastName: string;
}

export type ChangePasswordFields = {
OldPassword: string;
NewPassword: string;
ConfirmPassword: string;
}
```

## Current Behaviour / Output

Instead, it's just willy-nilly merging types that are obviously different, but just happen to be *partially* overlapping:

```typescript
export type Welcome = {
User: User;
}

export type User = {
Profile: ChangePassword;
ChangePassword: ChangePassword;
Notifications: ChangePassword;
}

export type ChangePassword = {
Title: string;
Error: string;
Success: string;
Submit: string;
Fields?: Fields;
}

export type Fields = {
OldPassword?: string;
NewPassword?: string;
ConfirmPassword?: string;
Email?: string;
FirstName?: string;
LastName?: string;
}
```

Why is it doing that?

## Steps to Reproduce

1. Paste the JSON above into the app
2. Set output language to Typescript

Options are not relevant. And also, I think it does a similar thing in other output languages, although I'm not an expert in all of them.

## Possible Solution

If partial overlaps must be merged for some reason, do it correctly, with `extends`. Not by smashing them together and making everything optional. Or better yet, to keep is simple - don't merge. At *least* don't produce an output that no longer matches the input precisely.

Contributor guide

Open the contributing guide

Research direction

Reproduce the JSON example through app.quicktype.io and the npm entry point with TypeScript output, then trace the type-merging behavior that combines partially overlapping object shapes. No source file or test is named in the issue; done means the generated types preserve the distinct input structures without incorrect optional properties, with regression coverage for this example.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.