-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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 hole with compatibility between optional parameters/extra parameters #3049
Comments
It basically comes down to: What type is a function assumed to accept for extra parameters, If extra parameters are considered If extra parameters are considered |
Here's a way to get the best of both worlds while maintaining soundness: Have extra parameters of a function type be
Here's an example: //@flow
interface Foo {
fooMethod(x: string): void;
}
let foo: Foo = {
// Implementing a function by omitting a parameter is ok, since the function will ignore the
// parameter so it can be considered as accepting `mixed` for extra parameters.
fooMethod(): void {}
};
interface Blah extends Foo {
// Implementing a function with another function that needs an extra optional parameter is
// ok, since extra parameters in Foo.fooMethod are considered `void`, which is compatible with
// string|void.
fooMethod(x: string, y: string|void): void;
}
// If you call a function literal with extra parameters (or function type inferred from a function
// literal), it's okay, because the extra parameters are `mixed`.
const x = () => 'hello';
x('foo');
// If you call a function type with extra parameters, the parameters must be compatible with
// `void`, since the function may be implemented by one which has hidden optional parameters.
const y = (a: number = 1): number => a;
const z: () => number = y;
z('foo'); // Error: string is incompatible with void
// For the same reason, you can't assign a function type to one accepting more parameters.
const w: (a: string) => number = z; // Error: string is incompatible with void Put differently, function types without rest parameters would have an implied rest parameter of |
@jesseschalken Is your proposal a breaking change for code like this? type F = (a: number) => string
type G = (a: number, b: string) => string
const f: F = a => a.toString()
const g: G = f |
@masaeedu Yes, it would be a breaking change for that code. A function compatible with |
I expected Flow to either report that
(number|void) => number
is incompatible with() => number
, or that() => number
is incompatible with(string) => number
. Either would fix this problem, but allowing both in combination is definitely unsound.The text was updated successfully, but these errors were encountered: