Skip to content

Recursive reverse mapped types don't work well with mixed object and tuple structures #55382

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Andarist opened this issue Aug 15, 2023 · 1 comment Β· Fixed by #56555
Closed
Labels
Help Wanted You can do this Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases
Milestone

Comments

@Andarist
Copy link
Contributor

πŸ”Ž Search Terms

inference recursive reverse mapped type tuples arrays

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried

⏯ Playground Link

https://www.typescriptlang.org/play?#code/C4TwDgpgBAygxgCwgWwIZQLxQEoTgewCcATAHgGdhCBLAOwHMAaKAV1oGtb8B3WgPigAfKIQipi+WgBsQrDl14BtALoBuAFDrQkKABEIAMzrVg1SaQAqArAG91UKIoDSUOlHYQQ+A1AvKAXFAAFEEAlJgCFs7K4cL6RrQmZrSW0XwaAL4a6sR4UqiiUAZscKaSUHCiqMAQllAQAB41tMTksIgoqHxBuQlJkoHxxmUpVqGBFtkEtJQiEOQsUsCYFVU1QXYOqIFhEVAAjIz2UABGgZsOFTvhGAIARHdHDhlHGaHZAPQfUMAI1G2SaCJOAQGSuWgGCCENoAAxsUG2UFoLGQJyhqlO5yuUEoNAYUAyBJh6lECyWGi+UAAegB+TTTWakxbAABMK0qYnWil2twOzG5N3ud2UMU+31+-yggPBkOhUBhyNRUJUMNOLGWJhxCHwi2IMqh8sUirRhH5uLo9BFxKZSxZFO+tPpkkZ82ZAGZ2WsIBtjoieQJDsczo5-VAHspXu9NJSJQDaNA6LLYfDEcaocxg+aGCoiWqNctyNrdfrCPKU4E06bMY4s5aiSTXUs3fbqTSgA

πŸ’» Code

type Schema = Record<string, unknown> | readonly unknown[];

type Definition<T> = {
  [K in keyof T]: (() => T[K]) | Definition<T[K]>;
};

declare function create<T extends Schema>(definition: Definition<T>): T;

const result = create({
  a: () => 1,
  b: {
    c: () => "",
  },
});

// this one nicely infers `{ a: number; b: { c: string } }`
result;
// ^?

const result2 = create([() => 1, [() => ""]]);

// this one infers `number[]` but it should infer `[number, [string]]`
result2;
// ^?

const result3 = create({
  a: () => 1,
  b: [() => ""],
});

// this one infers `{ a: number, b: string[] }` but it should infer `{ a: number, b: [string] }`
result3;
// ^?

πŸ™ Actual behavior

tuples can't be inferred recursively here

πŸ™‚ Expected behavior

tuples are inferred as arrays

Additional information about the issue

I understand that I need some tuple context to actually infer tuples but I've tried a couple of ways to add it and I just can't make it work. It would be much simpler if TS would just infer tuples here with the original code.

  1. an attempt with const type parameter: TS playground
  2. an attempt with adding a constraint to Definition: TS playground
  3. "routing"/resolving the T[K]'s constraint using a conditional type to satisfy the Definition's constraint: TS playground
  4. an attempt with changing Schema to use any over unknown to fix the recursive constraint problem: TS playground
  5. an attempt with a separate mapped type for the array constraint and routing to it: TS playground
@RyanCavanaugh RyanCavanaugh added Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases Help Wanted You can do this labels Aug 17, 2023
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Aug 17, 2023
@andreaTarascioSophany
Copy link

Hi! I would be excited to contributing fixing this issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Help Wanted You can do this Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases
Projects
None yet
3 participants