-
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
type for Function.prototype.bind wrongly preserves fields on a function #34338
Comments
BTW, this only happens when using this specific overload.
|
Certainly not the correct behavior, but we'd need some way of expressing "call signatures only", which isn't expressable with the current type system primitives |
But it really looks like it's just a matter of rewriting the first overload. bind<T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T): (...args: A) => R; |
declare function fn(s: string): number;
declare function fn(n: number): string;
const b = fn.bind({});
// Both OK, but argument capture can't preserve overloads
b(10).toLowerCase();
b("").toFixed(); |
I actually made that change before realising it broke the overload tests, and I couldn’t find a way to preserve them, which I guess is your point in #34338 (comment) Nice test coverage 👌 |
Upon thinking about it more, it might be possible by intersecting with a mapped type that excludes non- That said, adding that extra complexity would need to be justified by someone running into this in practice. It seems like a somewhat difficult mistake to make. Was this encountered in an actual manifested bug, or just something you noticed? |
No, I actually came across it. I had an API that allowed you to “partially apply” a function using fields on that function, which returned a function with the same interface until eventually it was called. I also needed to clone this function, and bind seemed like the easiest way to do it, however the fields didn’t get added despite the types saying they were.
I did also try the mapped type and couldn’t get it to work as the type system seemed to think that when you did that there were no callable signatures left either (I also remember having problem with the generic tests when doing this). That said I could easily have missed something in my implementation.
|
type RemoveProps<T> = { [K in keyof T]: never };
type SafeBind<T> = T & RemoveProps<T>;
interface Function {
bind2<T>(this: T, arg: any): SafeBind<T>;
}
function f(n: number): string;
function f(n: string): number;
function f(n: any) {
return n;
}
f.prop = 0;
const t = f.bind2(null);
t(0);
t("");
t.prop; // never |
|
When calling
bind
on a function Javascript does not copy the properties across that have been added to that function, however TS treats them as having been copied.TypeScript Version: 3.7-Beta
Search Terms: function bind
Code
Expected behavior:
hello
field should not be present ontypeof b
.Actual behavior:
hello
is deemed to exist ontypeof b
and the program crashes.Playground Link: http://www.typescriptlang.org/play/?ts=3.7-Beta&ssl=1&ssc=1&pln=7&pc=1#code/MYewdgzgLgBAhjAvDAFASiQPhgbxgXwCg4A6ACwFMAbKkJGAcjIEsHDDRJYAje075mAAmKHPjTtu5arRIQADlWZQUAIlUYA9JpgBVMMDgBXAOZlYAFQCe8igFEATg5AOAXDADCcMGBCwHFHBCMPLOtg5QVowKSlAMMCAAZjBGwhSJghRChEA
Related Issues: #212 seems to be where this was discussed and finally implemented, although it's not directly related.
The text was updated successfully, but these errors were encountered: