eslint-plugin-flowtype
eslint-plugin-flowtype copied to clipboard
Rule for requiring types for fn definitions only
One of Flow's goals was to provide an 'incremental' model, where users could incrementally migrate their code. As a user of this module, I have faced an overwhelming number of issues with the current "flowtype/require-parameter-type"
rule, which throws an error on every missing declaration. A rule that would complement flow's goal of 'incremental migration' would be a separate rule for requiring types for function definitions.
Ideally, it would do something like this:
function example(number) { // <-- require types here
return new Promise((resolve, reject) => {
resolve(someArray.map(each => each)) // <-- DO NOT require types here
})
}
There is the option excludeArrowFunctions
in both "flowtype/require-parameter-type"
and "flowtype/require-return-type"
. Does that work for you?
"flowtype/require-parameter-type"
throws way to many errors. For example, it would require the following type declarations in the example:
function example(number) { // <-- requires types here
return new Promise((resolve, reject) => { // <-- requires types here
resolve(someArray.map(each => each)) // <-- requires types here
})
}
Ideally, there should be a rule that only lints fn definitions or expressions:
function example(number) { // <-- requires types here only
return new Promise((resolve, reject) => {
resolve(someArray.map(each => each))
})
}
// or its expression equivalent
const example = (number) => { // <-- requires types here only
return new Promise((resolve, reject) => {
resolve(someArray.map(each => each))
})
}
@gajus would a PR for adding a "flowtype/require-fn-declarations-expressions-paramater-types"
be welcome?
Personally I don't use the require-*
rules as I feel they go against the power of Flow's inference. That said, I can understand the benefit of these rules purely for documentation purposes (although with IDE integration it kinda doesn't matter..).
While in your example the benefit is clear, on this example I think you'd expect type annotations on the inner function:
function blah(a, b) { // would require types
return function (c, d) { // would not require types, but probably should?
// ...
}
}
I think really you'd want some sort of metric to determine whether a function is "simple" (would not require types) or "complex" (would require types).
The current excludeArrowFunctions
option probably provides enough differentiation between simple & complex. It could probably do with an additional option for including arrow functions assigned to a variable though.
Or perhaps options to include only:
- function declarations
function x() {} // included
- arrow functions assigned to variables? (because it's quite common, usually serving the same role as function declarations)
const x = () => {} // included
- functions being returned (covering factory functions)
function x (a, b) { // included
return function (x, y) { // included
// ..
}
}
function x (a, b) { // included
return (x, y) => { // included
// ..
}
}
const x = (a, b) => { // included
return (x, y) => { // included
// ..
}
}
- class methods
class X {
x() {} // included
}
Basically just trying to cover "top-level" functions.
Maybe the term you're looking for is "named functions"? I think babel transforms const x = () => {}
to var x = function x() {};
, so it is actually named.
However, it appears ES6 arrow function have ''
as their .name
:(
@danharper Exactly. @opatut We also want to check anon functions as well.
Kind of an old ticket, but running into this as well. I'm kind of anal so I want more type annotations than less, but requiring that I annotate Promise(resolve => ...)
is a bit much.
We use
export const moduleFn = (number) => { // <-- requires types here only
return new Promise((resolve, reject) => {
resolve(someArray.map(each => each))
})
}
We don't want to refactor all our code to use
export const function moduleFn = (number) => ....
A rule that distinguishes exported arrows would be perfect
Another case I've been annoyed by this rule is when I'm overriding a method in a subclass. The superclass already has the parameter type annotated, so it feels silly to have to annotate it again. And frequently the type isn't exported from the superclass.
I think that requiring types for exported functions is what we need. Inside a module flow inferences all the types.