-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Inconsistent Parameter Type Inference for Functions with Default Values #60222
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
Comments
Looks like a duplicate of #59643 |
There's an interaction here with the contextual type that's a bit subtle. Consider this sequence of calls: declare function foo<T extends string | number>(callback: (arg: T) => void): (arg: T) => T;
const p1 = foo(n => n)("hello"); // OK
const p2 = foo((n?) => {
return n
})("hello"); // OK;
const p3 = foo((n?) => {
n = n ?? 2;
return n
})("hello"); // OK;
const p4 = foo((n = 2) => {
return n
})("hello"); // OK; If For the most part, TS views parameter defaults as an implementation detail of the function, not an intrinsic part of the signature. |
( Presumably you either want Sure, but given that |
It's also close to #58977 which basically proposes the same interaction at call sites |
Thanks, @jcalz and @RyanCavanaugh! I've made a workaround that works perfectly for my needs: type AnyActions = Record<string, any>;
// Utility type to infer parameters for functions supporting default parameters and the `this` keyword
type InferParametersWithContext<F extends Record<any, any>, T extends any = undefined> = {
// Iterate over each key in the action mapping
[Key in keyof F]:
// Check if the function matches the expected structure
F[Key] extends (...params: infer A) => infer R ?
// If so, infer the parameters and return type while specifying `this` context
(this: T, ...params: A) => R :
// Otherwise, fallback to using the original function's parameters and return type
(this: T, ...params: Parameters<F[Key]>) => ReturnType<F[Key]>
};
type Options<F extends AnyActions> = {
actions?: InferParametersWithContext<F, {source: number}>;
}; Thanks again! I believe the issue can be closed now. |
🔎 Search Terms
"parameter type inference" "default parameters" "function type inference issue" "any type" "inconsistent type inference" "default value"
🕗 Version & Regression Information
I started observing this behavior in TypeScript version 5.5.4, and it has continued in the latest stable release 5.6.3.
Yes, I have tested the latest nightly version (5.7.0-dev.20241014), and the issue persists.
I have not yet bisected the issue with every-ts, but I will consider doing this to identify the specific change.
I have tested the issue in the TypeScript Playground with versions back to 3.3, and the problem is reproducible across multiple versions.
⏯ Playground Link
https://www.typescriptlang.org/play/?ts=5.6.3#code/PTAEBUAsFNQMQK4DsDGAXAlgeyQZ1AAZqQa4GgDW0AngO5YBOAJqCjmtAB5oBQa1AB1hwkAYXZc0oALygA3j1BLQuLAgYpoALlAAlaG2YAeXGgYYkAcwA0oAIZJqAPh4BfHjxAQYoAGbJ0bCRQJmhfCwxMHD5BYSQjcBl4MQluWwAFUEloJCZ8B2oAbQBdJIKS210kgDcsDCYnJIAKYlIdcFsAOm6BOwY7AFtcHXSAShlG3Q9+IVAAQUcRJP1DJhMzCxtklxjZgHkBKLwjOCzuHLz5xaRG2QVle0CcXAB+HTg3D39UI9ABBiwln6AwSZw4uXwC2oIicTSwhyCw1AByOuASTnGclA7k8YD26lAEUwdgANvY0BwBodQGgsI8SNBqrB-vDoAwabFCUhfGycpoeCygYMmvdlHYnngdKKHkpfFgsE0BEkAEyY1y2LwASTwHDsLCwvi5PIY5isoAA5EgEAMAEZs822cCxADKKHM1PhaHwcvZ5oK5s681Y6mwCHwKEgdU0tgsoWgTE6ihlSmguAEip0VttbJVao1YAAopwBCSMChIhyBJt7CSSVhaPhWo26fQGBR7PgLODQgmk8mbVgbU0kVm7Qw1aAvFBSKAcLBWf0OPhcAN5cQSdRbAwwiSDJgzcRYFwhOh46A7ZA7NVsOyDRAXW6MIdEw93K5RjwgA
💻 Code
🙁 Actual behavior
The
foo
function is inferred as(method) foo(this: FnContext, p?: any): void
, which is unexpected and undesired.The
esp
andbob
functions behave as expected.🙂 Expected behavior
foo
function should have itsp
parameter type inferred asnumber
, due to the default value provided.esp
function behaves correctly, withp
inferred asnumber
.bob
function should remain unaffected and should correctly infers
asnumber
.Additional information about the issue
I have attempted various approaches, including changing the default parameter type to an empty tuple (TypeScript Playground) and using conditional types (TypeScript Playground), but none resolved the underlying issue.
The issue seems to stem from how TypeScript handles parameter inference in the context of default values, leading to unexpected
any
types.If possible, I would appreciate any guidance on how to achieve the desired inference without resorting to explicit typing for each parameter. Additionally, any insights into whether this behavior is expected or if it may be addressed in future versions would be greatly appreciated.
The text was updated successfully, but these errors were encountered: