Skip to content

isPlainFunction

Checks whether a value is a plain function.

A plain function is a user-defined callable created via a function declaration, function expression, arrow function, async function, or generator function.

This helper intentionally excludes class constructors, built-in/native functions, and functions created via the Function constructor.

It never throws an error and never mutates input. Use it when you need to ensure that a value is a safe, lexically-scoped function suitable for callbacks, handlers, middleware, or other user-defined execution points.

Signature

function isPlainFunction(
  value: unknown
): value is (...args: readonly unknown[]) => unknown

Parameters

Name Data type Description
value unknown The value to check. Must be a function (per JavaScript's typeof semantics), including class constructors, async functions, generator functions, and bound functions.

Returns

Boolean:

  • true: If the value is a plain function.
  • false: Otherwise.

Behavior

  • Accepts:
  • Function declarations: function fn() {}
  • Function expressions: const fn = function () {};
  • Arrow functions: const fn = () => {};
  • Async functions: const fn = async () => {};
  • Generator functions: function* fn() {}
  • Rejects
  • Class constructors: class Foo {}
  • Built-in and native functions: Date, Map
  • Functions created with the Function constructor: new Function("return 1")
  • Non-functions of any kind.

Implementation Notes

Uses Function.prototype.toString to distinguish between:

  • User-defined functions.
  • Class constructors.
  • Native and built-in functions.
  • Dynamically generated functions.
  • Functions created with the Function constructor are rejected by design because:
  • They do not close over lexical scope.
  • They are equivalent to eval.
  • They are security-sensitive and rarely appropriate for callbacks.
  • This helper does not invoke the function.
  • This helper does not inspect prototypes or constructors, as those approaches are unreliable across async and generator functions.
Examples
isPlainFunction(function () {}) // true
isPlainFunction(() => {}) // true
isPlainFunction(async () => {}) // true
isPlainFunction(function* gen() {}) // true

isPlainFunction(class Foo {}) // false
isPlainFunction(Date) // false
isPlainFunction(new Function("return 1")) // false
isPlainFunction("fn") // false

Notes

  • This is a semantic type guard, not a structural one.
  • If a broader definition of "callable" is needed, including classes or native functions, use a different helper such as isCallable.
  • This helper is pure, side-effect free, and never throws.

Suitable for validating user-provided callbacks, hooks, lifecycle handlers, and other execution points where only safe, user-defined functions are allowed.