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
Functionconstructor 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.