Skip to content

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

Closed
@Andarist

Description

@Andarist

πŸ”Ž 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Help WantedYou can do thisPossible ImprovementThe current behavior isn't wrong, but it's possible to see that it might be better in some cases

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions