-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Return type of partially applied bound generic function #47899
Comments
For the case where you exhaust all the arguments, there's really no reason to use For the case where you don't exhaust all the arguments, we don't have a type that can represent that - there's not a type annotation on function a<T extends Array<any>>(anArray: T, s: T): T {
return anArray;
}
// b: ??
let b = a.bind(undefined, [1]); // b has type () => any[] |
Can you explain why? I'm currently trying to map an object with functions that conform to a specific (albeit generic) interface to function types that retain their generic-ness, and I think it's related to this issue. In other words, say I have this the following (a super-reduced version of my use-case): /* example 1 */
type Functions = Record<string, ((data: any, errorMessage?: string) => any)>
const fns = (() => {
function number(data: string, errorMessage?: string): number
function number(data: any, errorMessage?: string): { output: 0 }
function number<T>(data: T, errorMessage?: string): number | { output: 0 } {
// Do something with errorMessage ...
if (typeof data === 'string') {
return Number(data)
}
return { output: 0 }
}
return { number }
})() satisfies Functions
let foo1 = fns.number({}) // { output: 0 }
let bar1 = fns.number('hi') // number Now say I want to support this pattern: /* example 2 */
let doWith = <T, F extends Functions>(value: T, fns: F) => {
const returnVal = {} as {
[K in keyof F]: (errorMessage?: Parameters<F[K]>[1]) => ReturnType<F[K]> // ??
}
for (const [key, value] of Object.entries(fns)) {
returnVal[key as keyof F] = value.bind(value, value)
}
return returnVal
}
let foo2 = doWith({}, fns).number() // { output: 0 }
let bar2 = doWith('hi', fns).number() // { output: 0 } but should be number IMO there's enough information here for TypeScript to properly infer types, there's just no syntax for it. In other words, the problem is here: const returnVal = {} as {
[K in keyof F]: Bind<F[K], [T, T]> // Β―\_(γ)_/Β― - basically some way to pass the type to the function type
} TypeScript knows what each function produces in terms of type based on an input type, and that type is known by likewise knowing the input type of the parent function. None of these types are dynamic and they are statically analyzable. @RyanCavanaugh - re-thinking it, maybe what you are saying is that there isn't currently a type annotation that can do this, in which case this would be a feature request instead of a bug report? In which case, what about a top-level |
In other words, a bind statement should be considered by TypeScript to be something like this: function something<const T>(data: T, message?: string): T {
console.log(message)
return data
}
const foo = something.bind(undefined, ['bar'])
// Type of `foo` should be (message?: string) => readonly ['bar'] I don't understand any (technical) reason why that can't be inferred? The information for inference is all there. |
Bug Report
π Search Terms
partial application generic bind return type
π Version & Regression Information
β― Playground Link
Playground link with relevant code
π» Code
π Actual behavior
The types of b and c are different, and the types of d and e are different.
π Expected behavior
I'd expect them to both have the same type (b that of c,
() => number[])
, d that of e() => string
), as the expressions are doing the same thing (arrow function vs bind for partial application of a function).This limitation is noted in a comment to the "Strict bind, call, and apply methods on functions" PR, but I couldn't find an actual issue referencing this behaviour.
That comment is also mentioned as a known limitation in a similar issue which was closed in #28920, but unfortunately that pr only fixes the issue when binding only this, and not other parameters.
The text was updated successfully, but these errors were encountered: