Skip to content
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

Add a built-in helper type for dotted object path literals and path tuples #46337

Closed
5 tasks done
thw0rted opened this issue Oct 13, 2021 · 4 comments
Closed
5 tasks done
Labels
Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript

Comments

@thw0rted
Copy link

Suggestion

🔍 Search Terms

object key dotted path template literal helper type

✅ Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

I'd like to see a built-in helper type that takes an interface as a generic param, and returns either the union of all dotted-notation key paths, or tuples of valid paths:

interface Foo {
  a: {
    b: {
      c: number;
    }[];
    d: boolean;
  }
}

type FooPath = ObjectKeyPath<Foo>; // "a" | "a.b" | `a.${number}.c` | "a.d";
type FooTuple = ObjectKeyTuple<Foo>; // ["a"] | ["a", "b"] | ["a", number, "c"] | ["a", "d"];

📃 Motivating Example

Both of these notations are commonly used in libraries around the ecosystem. Many end users try to create similar complex types themselves, with results of varying quality, that may miss important edge cases or perform much worse than an optimal implementation would. I understand that there may have to be similar limitations on a built-in type, for recursive or excessively-deep inputs, but these could at least be thoughtfully designed and documented, with useful error messages.

💻 Use Cases

@MartinJohns
Copy link
Contributor

See #39522 (comment):

We've opted to not include utility type aliases in the lib unless they're required for declaration emit purposes.

@thw0rted
Copy link
Author

I forgot to link #12290 and #20423. The former workshops implementing such a helper type (it's interesting to watch it evolve over the years as TS adds new features!) while the latter proposes a keyword. If a keyword is preferable, I wouldn't have a problem with that, but it sounds like that would have the same potential downsides (introducing naming conflicts with existing code) so there's probably no reason for that.

I'm not sure what Ryan means when he says "required for declaration emit purposes" -- I was just hoping to see something like one of these, which were still being added as recently as v3.5.

@andrewbranch andrewbranch added Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript labels Oct 13, 2021
@andrewbranch
Copy link
Member

FWIW I’m also not sure about the “required for declaration emit purposes” comment, but to add a bit of context, I think the moment where we really started souring on adding more utility types was after we shipped Omit, when the community was split on whether the key type K should extend keyof T (the object type) or not. There were reasonable arguments on both sides, and I don’t know what the actual ratio was, but it felt like no matter what we did, at least half of all people were going to be annoyed. Omit was so ubiquitous that it felt worthwhile to take it on, but I’m honestly not sure whether we would have made the same decision (over not shipping it at all) today. So for any utility type that is less ubiquitous than Omit, it now feels pretty easy to say it doesn’t meet the bar.

@thw0rted
Copy link
Author

Maybe the best way forward would be to double down on #20423? My main reason for wanting something built-in was that, unlike Omit, the implementation of this feature is fundamentally non-trivial. It's very easy to miss edge cases and/or tank performance, and it's also easy to wind up with error messages when type-check fails that are difficult if not impossible to decipher. A keyword would solve all those problems, or at least the team could independently decide (and document!) that it's simply not feasible to implement in a performant, easy-to-reason-about way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

3 participants