-
Notifications
You must be signed in to change notification settings - Fork 12.2k
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
Optional parameters instantiated from generic params add | undefined
to the type
#58578
Comments
Yeah, it's purely a display issue. It's legal to pass declare const fn: Expected;
fn(undefined); // fine, no error |
@fatcerberus Right, in terms of the current behavior it has no effect on type safety. Theoretically though, there are some niche cases where it could lead to semantically different results were it treated the same way as EDIT: Actually I take that back, there are some niche cases where it could cause incorrect inference if the function ends up being used to infer out params like this: type Arg = ((arg?: number) => void) extends (arg?: infer t) => void ? t : never
// ^? number |
It looks like inference, at least, is consistent in that case: type ExpectedArg = Expected extends (arg?: infer t) => void ? t : never
// ^? type ExpectedArg = number
type FailArg = Fail extends (arg?: infer t) => void ? t : never
// ^? type FailArg = number |
@fatcerberus Interesting you could use this as a workaround potentially. That said, it is still a (small) type-safety issue due to the inconsistency if you extract our your parameters like that. |
I believe the type system treats |
@fatcerberus Ahh you're right, I see what you mean now. I'm not a big fan of that either though. If a type has some special casing that results in it being treated equivalently to another type externally, it should always be displayed in the normalized form IMO. It's very confusing to try and What I meant about EOPT was that if you consider a situation like this: type NumericOptionalUnary = (arg?: number) => void
const f: NumericOptionalUnary = (...args) => {}
I actually have to make this distinction for inline snapshots in attest: Explicit |
Yeah, optional params are weird, even in JS: function foo(x = 42) {
console.log(x);
}
foo(undefined); You might expect that to print |
Not sure if this is helpful or not, but this is a pattern I've been using to tell the difference between a user explicitly passing |
@fatcerberus Wow thanks, I didn't know that. At least it's still better than how Python handles default arg values π @ahrjarrett Based on what @fatcerberus mentioned, I don't think that works: You probably are stuck using spread args and checking length. |
Not sure I follow -- the behavior in your screenshot is the behavior I'd expect @ssalbdivad. Are you saying you want the user to be able to pass undefined? You can also use an overload for each valid set of arguments the user can provide, and spread the args in the implementation, checking (like you said) for argument length to determine which overload you're handling. Type inference works great, it's more explicit for the caller, and you still get good type inference in the body of the function. |
@ahrjarrett Maybe I misunderstood, but you mentioned
In this example you gave, you can't differentiate as written, no? That's why I mentioned you'd have to use a variadic parameter and check the length like I do when handling inline snapshots. |
π Search Terms
generic function optional undefined ? modifier return infer inferrence
π Version & Regression Information
β― Playground Link
https://tsplay.dev/w199kw
π» Code
π Actual behavior
(see example)
π Expected behavior
(see example)
Additional information about the issue
I don't think this is likely to cause type-safety issues. It's primarily just visual clutter and inconsistency with the standard behavior.
The text was updated successfully, but these errors were encountered: