-
Notifications
You must be signed in to change notification settings - Fork 0
Function declarations vs. arrow functions in TypeScript #141
Description
In JavaScript, we used to prefer function declarations because they 1. are hoisted (can be called before they are defined, which can be helpful for circular dependencies) and 2. visually clearly contain the function keyword.
With TypeScript, I came to the conclusion that arrow functions have better properties because they allow type annotation. This means that I can, for example, import a function type from a framework (e.g., the type for an Express middleware) and the function argument and return types are inferred from the type.
import type { RequestHandler } from "express";
const middleware: RequestHandler = (req, res, next) => {
// ...
};Now I've noticed a small disadvantage of arrow functions. With arrow functions, you can't use the assert annotation so easily. If you use it, the following error appears at the call site: “Assertions require every name in the call target to be declared with an explicit type annotation.”
The assert notation must then be specified in the variable type declaration:
// Will show an error at the call site
const assert = (value: unknown): asserts value => {
if (!value) {
throw new Error("Assertion failed");
}
};
// Works
const assert: <Value>(
value: Value,
message?: string,
) => asserts value = (
value,
) => {
if (!value) {
throw new Error("Assertion failed");
}
};This is a minor inconvenience. Personally, I prefer function declarations and they are used pretty often in code examples in React, Next.js and Remix. If TypeScript finds a syntax to specify a type declaration for a function declaration, I would like to switch back to function declarations.