-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Keyword for inferring a new type from destructured parameters #55908
Comments
from is already a keyword, so I am guessing that some parts of the esm parser have to be rewritten. Aside from that, my opinion is that if certain properties can be by themselves (i.e. first and last name) they should be properly named interfaces. Typehints would require some modifications as it has to show the notion of "this is a subset of type Person, with only these properties in consideration" A good case for this would be to improve duck typing experience and testing. I don't see how its harmful as long as the developer fully understands the implications |
Indeed, I just used Some alternative names could be:
In ideal scenarios, I agree with this to 100%. But there are cases where being this explicit doesn't really matter (like in the above examples), or where you don't control the source of the type (e.g. external lib/generated). But the point of having this keyword (or something similar) is to have the ability to opt-in to this where it makes sense; I agree that this is not always the case!
Awesome, thanks for your feedback! |
If TS was not tied to JS, I would think that this is a good idea. But I suspect that it could cold make things more difficult to keep a good level of compatibility with thew new iterations of ECMAScript. One example that comes to my mind is this RFC: https://github.com/tc39/proposal-type-annotations . My intuition tells me that using a new keyword (instead of If we use a keyword of some sort, I suggest to place it after Regarding "prefixes" (as in the case of |
Fair point. We definitely need to make sure that this is something that is opt-in and takes into consideration upcoming changes to the language. I'll see what I can find on the horizon, if any more examples come to mind, let me know!
I think I agree with this, but I would love some more feedback on naming/structure before updating the OP.
Thanks for your feedback, I'll make sure to read a bit more on TC39 |
My mind says the world here should be "satisfies" const formatName = ({ first, last }: satisfies Person) => `${first} ${last}`; This would not work for the variable-destructor case though const { first, last } = p satisfies Person; // requires it to actually be a Person |
@Dimava |
I was thinking along the same lines, but it's not really in line with how the keyword is used today. The discussion thus far has been great—thanks to everybody who's been participating! 🙌 So far, this is what I have gauged from the discussion (here and on Reddit):
Aside from "what to call this keyword" (if |
It would be nice for this to be possible when the destructured argument's type is inferred. Consider my use case:
In my case, allowing this on the
|
🔍 Search Terms
Issue #42419 (+ #48220) discusses changing the current behavior of TypeScript to address the same underlying issue.
My proposal is different as it introduces a new explicit language feature and does not change any current behavior.
I also found #7576. The essence here is that they want some sort of shorthand for destructured parameter types.
I think this is vaguely related to my proposal since it addresses a way to do that—it touches on a similar pain point.
✅ Viability Checklist
⭐ Suggestion
Let's introduce a feature that allows for TypeScript to infer a new type from destructured function parameters.
To conceptualize this idea, I'm introducing a new keyword called
from
which can be used after:
when destructuring a function parameter:This declares that
typeof isAdult
is(person: Pick<Person, "age">) => ...
instead of(person: Person) => ...
meaning that any object matching{ age: number }
can be passed in as a parameter.You could also potentially do this when destructuring a local variable, though, I struggle to see its usefulness:
I'm not even sure whether this should be legal.
📃 Motivating Example
We often use destructuring in functions, because it helps us stay DRY:
I think this is good practice and a sensible thing to include in your company style guide.
But if we look critically at the above snippet, we can see that the signatures for both
formatName
andisAdult
are lying about their implementation. They (quite excessively) declare that they need all properties fromPerson
when they actually only need a few. And rightly so: I have explicitly declared that by writing: Person
, but my intention here was actually to be able to pass any object that matches{ age: number }
intoisAdult
(for example).To solve this, I have to jump through some hoops, either like this …
... or the inverse:
However…
… the first solution is noisy and un-DRY since have to write the "pick part" twice: first for the destructuring itself, and then for the
Pick
type. Note: this effect is greatly exacerbated as the number of properties of a type increases, so this example is quite tame in that regard.… the second solution (workaround?) feels too verbose for my use case (there's too much detail), I have no intent of re-use for the
Aged
orNamed
type. If thePerson
type comes from a third-party library (or another source that I don't control, e.g. Prisma), then this option is out of the question entirely as I can't "build up" my own type from smaller fragments (i.e.Person = Aged & Named
).This means that the first solution is often the only viable option—and it just isn't a great experience.
So—with the addition of the
from
keyword (or something similar), this headache is entirely relieved! It would make it much more convenient to declare the explicit requirements of a function to effortlessly make your code more expressive.💻 Use Cases
This would have great utility in React components where you just want to pick a few props out of e.g.
ButtonProps
from@mui/material/Button
:However, I see many use cases for this: Anywhere where you need more generically defined function type signatures without having to create a new explicit type or use
Pick
/Omit
.You need to manually use
Pick
/Omit
or break types into smaller (often hard-to-name) types and compose them later on, or just live with the "excessive" type definitions.The above 👆
The text was updated successfully, but these errors were encountered: