func-style

Enforce one way to define functions: declarations, or expressions assigned to variables

A function declaration can be called above the line that defines it. A function assigned to a variable only exists after that line has run. If a project mixes both, you have to check how each function is written to know where it can be called.

This rule makes you pick one. By default it asks for expressions.

Configure#

Off by default. To turn it on:

bunfig.toml
[lint.rules]
"func-style" = "error" # or "warn"

Every option, set to its default. The ones that are commented out are unset by default.

bunfig.toml
[lint.rules]
"func-style" = [
  "error",
  "expression", # "declaration" or "expression"
  {
    allowArrowFunctions = false,
    allowTypeAnnotation = false,
    overrides = {
      # namedExports = <"declaration", "expression" or "ignore">,
    },
  },
]

Examples#

example.js1 problem
function formatName(user) {
  return `${user.first} ${user.last}`;
}
example.jsNo problems
const formatName = function (user) {
  return `${user.first} ${user.last}`;
};

const initials = (user) => user.first[0] + user.last[0];

export default function is never reported, and neither is a TypeScript function that has overload signatures:

example.tsNo problems
export default function main() {}

function parse(input: string): string;
function parse(input: number): number;
function parse(input: string | number) {
  return input;
}

Options#

bunfig.toml
[lint.rules]
func-style = ["error", "declaration", { allowArrowFunctions = true }]
OptionWhat it does
"expression" (default)Report function declarations.
"declaration"Report functions assigned to a variable where it's declared.
OptionDefaultWhat it does
allowArrowFunctionsfalseWith "declaration", allow arrow functions.
allowTypeAnnotationfalseWith "declaration", allow a function if its variable has a type annotation.
overrides.namedExportsnot setThe style for export function and export const: "declaration", "expression", or "ignore" for either.

"declaration"#

example.jswith "declaration"2 problems
const formatName = function (user) {
  return `${user.first} ${user.last}`;
};

const initials = (user) => user.first[0] + user.last[0];
example.jswith "declaration"No problems
function formatName(user) {
  return `${user.first} ${user.last}`;
}

An arrow function that uses this isn't reported, because this would mean something else in a declaration:

example.jswith "declaration"No problems
function Timer() {
  const tick = () => {
    this.seconds++;
  };
  setInterval(tick, 1000);
}

allowArrowFunctions#

example.jswith "declaration", { "allowArrowFunctions": true }No problems
const initials = (user) => user.first[0] + user.last[0];

allowTypeAnnotation#

You can't give a declaration a function type as a whole, so this option lets those functions stay expressions:

example.tswith "declaration", { "allowTypeAnnotation": true }No problems
type Handler = (event: Event) => void;

const onClick: Handler = (event) => {
  event.preventDefault();
};

overrides.namedExports#

example.jswith "expression", { "overrides": { "namedExports": "declaration" } }No problems
export function formatName(user) {
  return user.name;
}

const trim = function (text) {
  return text.trim();
};
example.jswith "expression", { "overrides": { "namedExports": "declaration" } }1 problem
export const formatName = function (user) {
  return user.name;
};