isFunction
Checks whether a value is of function type.
Basic Usage
typescript
import { isFunction } from 'radash'
console.log(isFunction(() => {})) // true
console.log(isFunction(function() {})) // true
console.log(isFunction(async () => {})) // true
console.log(isFunction('hello')) // false
console.log(isFunction(123)) // false
console.log(isFunction({})) // false
Syntax
typescript
function isFunction(value: any): value is Function
Parameters
value
(any): The value to check
Return Value
Returns a boolean value, true
if the value is a function, false
otherwise. Also serves as a TypeScript type guard.
Examples
Basic Type Checking
typescript
import { isFunction } from 'radash'
// Function types
console.log(isFunction(() => {})) // true
console.log(isFunction(function() {})) // true
console.log(isFunction(async () => {})) // true
console.log(isFunction(function*() {})) // true
console.log(isFunction(() => 'hello')) // true
// Non-function types
console.log(isFunction('hello')) // false
console.log(isFunction(123)) // false
console.log(isFunction(true)) // false
console.log(isFunction(null)) // false
console.log(isFunction(undefined)) // false
console.log(isFunction([])) // false
console.log(isFunction({})) // false
Different Function Type Checking
typescript
import { isFunction } from 'radash'
// Arrow function
const arrowFunc = () => 'hello'
console.log(isFunction(arrowFunc)) // true
// Normal function
function normalFunc() { return 'hello' }
console.log(isFunction(normalFunc)) // true
// Async function
async function asyncFunc() { return 'hello' }
console.log(isFunction(asyncFunc)) // true
// Generator function
function* generatorFunc() { yield 'hello' }
console.log(isFunction(generatorFunc)) // true
// Constructor function
function Constructor() { this.name = 'test' }
console.log(isFunction(Constructor)) // true
// Class constructor
class MyClass {}
console.log(isFunction(MyClass)) // true
Type Guard Usage
typescript
import { isFunction } from 'radash'
function processValue(value: unknown) {
if (isFunction(value)) {
// TypeScript knows value is a function
console.log('Processing function:', value.name || 'anonymous')
return value()
}
console.log('Not a function')
return null
}
console.log(processValue(() => 'hello')) // Processing function: anonymous hello
console.log(processValue('not a function')) // Not a function null
Array Filtering
typescript
import { isFunction } from 'radash'
const mixedArray = [
() => 'hello',
'string',
123,
function() { return 'world' },
async () => 'async',
{},
[]
]
const functions = mixedArray.filter(isFunction)
console.log(functions.length) // 3
const nonFunctions = mixedArray.filter(item => !isFunction(item))
console.log(nonFunctions.length) // 4
Object Property Checking
typescript
import { isFunction } from 'radash'
const obj = {
name: 'Alice',
age: 25,
greet: () => 'Hello!',
calculate: function(a: number, b: number) { return a + b },
async fetchData() { return 'data' },
isActive: true
}
const functionProperties = Object.entries(obj)
.filter(([key, value]) => isFunction(value))
.map(([key, value]) => ({ key, type: value.constructor.name }))
console.log(functionProperties)
// [
// { key: 'greet', type: 'Function' },
// { key: 'calculate', type: 'Function' },
// { key: 'fetchData', type: 'AsyncFunction' }
// ]
Event Handler Checking
typescript
import { isFunction } from 'radash'
const eventHandlers = {
onClick: () => console.log('clicked'),
onSubmit: function(data: any) { console.log('submitted', data) },
onError: null,
onLoad: undefined,
onResize: 'not a function'
}
const validHandlers = Object.entries(eventHandlers)
.filter(([key, value]) => isFunction(value))
.reduce((acc, [key, value]) => {
acc[key] = value
return acc
}, {} as Record<string, Function>)
console.log(Object.keys(validHandlers)) // ['onClick', 'onSubmit']
API Response Processing
typescript
import { isFunction } from 'radash'
interface ApiResponse {
data: unknown
handlers: Record<string, unknown>
callbacks: unknown[]
}
function processApiResponse(response: ApiResponse) {
const validHandlers = Object.entries(response.handlers)
.filter(([key, value]) => isFunction(value))
.reduce((acc, [key, value]) => {
acc[key] = value as Function
return acc
}, {} as Record<string, Function>)
const validCallbacks = response.callbacks.filter(isFunction)
return {
data: response.data,
validHandlers,
validCallbacks
}
}
const response: ApiResponse = {
data: { id: 1, name: 'Alice' },
handlers: {
success: (data: any) => console.log('Success:', data),
error: 'not a function',
complete: () => console.log('Complete')
},
callbacks: [
() => 'callback1',
'not a function',
() => 'callback2'
]
}
const processed = processApiResponse(response)
console.log(Object.keys(processed.validHandlers)) // ['success', 'complete']
console.log(processed.validCallbacks.length) // 2
Plugin System
typescript
import { isFunction } from 'radash'
interface Plugin {
name: string
init?: Function
destroy?: Function
render?: Function
}
function validatePlugin(plugin: unknown): plugin is Plugin {
if (typeof plugin !== 'object' || plugin === null) return false
const p = plugin as any
if (typeof p.name !== 'string') return false
if (p.init !== undefined && !isFunction(p.init)) return false
if (p.destroy !== undefined && !isFunction(p.destroy)) return false
if (p.render !== undefined && !isFunction(p.render)) return false
return true
}
const validPlugin: Plugin = {
name: 'MyPlugin',
init: () => console.log('Plugin initialized'),
render: () => '<div>Plugin content</div>'
}
const invalidPlugin = {
name: 'InvalidPlugin',
init: 'not a function'
}
console.log(validatePlugin(validPlugin)) // true
console.log(validatePlugin(invalidPlugin)) // false
Middleware System
typescript
import { isFunction } from 'radash'
type Middleware = (req: any, res: any, next: Function) => void
function validateMiddleware(middleware: unknown): middleware is Middleware {
return isFunction(middleware) && middleware.length >= 2
}
const validMiddleware: Middleware = (req, res, next) => {
console.log('Processing request')
next()
}
const invalidMiddleware = 'not a function'
const middlewareArray = [
validMiddleware,
invalidMiddleware,
(req: any, res: any) => console.log('No next parameter'),
(req: any) => console.log('Missing parameters')
]
const validMiddlewares = middlewareArray.filter(validateMiddleware)
console.log(validMiddlewares.length) // 1
Configuration Validation
typescript
import { isFunction } from 'radash'
interface Config {
port: number
host: string
handlers: Record<string, unknown>
validators: unknown[]
}
function validateConfig(config: Config) {
const errors: string[] = []
// Validate handlers
Object.entries(config.handlers).forEach(([key, value]) => {
if (!isFunction(value)) {
errors.push(`Handler '${key}' must be a function`)
}
})
// Validate validators
config.validators.forEach((validator, index) => {
if (!isFunction(validator)) {
errors.push(`Validator at index ${index} must be a function`)
}
})
return errors
}
const config: Config = {
port: 3000,
host: 'localhost',
handlers: {
onRequest: (req: any) => console.log(req),
onResponse: 'not a function',
onError: () => console.log('Error')
},
validators: [
(data: any) => data.id > 0,
'not a function',
(data: any) => data.name.length > 0
]
}
console.log(validateConfig(config))
// ['Handler \'onResponse\' must be a function', 'Validator at index 1 must be a function']
Callback Function Processing
typescript
import { isFunction } from 'radash'
function executeCallback(callback: unknown, ...args: any[]) {
if (!isFunction(callback)) {
console.warn('Callback is not a function')
return
}
try {
return callback(...args)
} catch (error) {
console.error('Callback execution failed:', error)
}
}
// Valid callback
executeCallback((name: string) => `Hello ${name}!`, 'Alice')
// Output: Hello Alice!
// Invalid callback
executeCallback('not a function', 'Alice')
// Output: Callback is not a function
Event System
typescript
import { isFunction } from 'radash'
class EventEmitter {
private events: Record<string, Function[]> = {}
on(event: string, listener: unknown) {
if (!isFunction(listener)) {
throw new Error('Listener must be a function')
}
if (!this.events[event]) {
this.events[event] = []
}
this.events[event].push(listener as Function)
}
emit(event: string, ...args: any[]) {
const listeners = this.events[event] || []
listeners.forEach(listener => {
if (isFunction(listener)) {
listener(...args)
}
})
}
}
const emitter = new EventEmitter()
// Add valid listener
emitter.on('message', (data: any) => console.log('Received:', data))
// Try to add invalid listener
try {
emitter.on('error', 'not a function')
} catch (error) {
console.log('Error caught:', error.message) // Listener must be a function
}
emitter.emit('message', 'Hello World') // Received: Hello World
Utility Function Checking
typescript
import { isFunction } from 'radash'
const utils = {
format: (value: any) => value.toString(),
validate: (value: any) => value !== null,
transform: 'not a function',
process: null
}
const functionUtils = Object.entries(utils)
.filter(([key, value]) => isFunction(value))
.reduce((acc, [key, value]) => {
acc[key] = value as Function
return acc
}, {} as Record<string, Function>)
console.log(Object.keys(functionUtils)) // ['format', 'validate']
Async Function Checking
typescript
import { isFunction } from 'radash'
const asyncFunctions = {
fetchData: async () => 'data',
processData: async (data: any) => data.toUpperCase(),
syncFunction: () => 'sync',
notFunction: 'string'
}
const validAsyncFunctions = Object.entries(asyncFunctions)
.filter(([key, value]) => isFunction(value))
.map(([key, value]) => ({
name: key,
isAsync: value.constructor.name === 'AsyncFunction'
}))
console.log(validAsyncFunctions)
// [
// { name: 'fetchData', isAsync: true },
// { name: 'processData', isAsync: true },
// { name: 'syncFunction', isAsync: false }
// ]
Function Parameter Checking
typescript
import { isFunction } from 'radash'
function analyzeFunction(func: unknown) {
if (!isFunction(func)) {
return { isValid: false, reason: 'Not a function' }
}
const f = func as Function
return {
isValid: true,
name: f.name || 'anonymous',
length: f.length,
isAsync: f.constructor.name === 'AsyncFunction',
isGenerator: f.constructor.name === 'GeneratorFunction'
}
}
console.log(analyzeFunction(() => {}))
// { isValid: true, name: 'anonymous', length: 0, isAsync: false, isGenerator: false }
console.log(analyzeFunction(async (a: number, b: number) => a + b))
// { isValid: true, name: 'anonymous', length: 2, isAsync: true, isGenerator: false }
console.log(analyzeFunction('not a function'))
// { isValid: false, reason: 'Not a function' }
Function Composition
typescript
import { isFunction } from 'radash'
function compose(...functions: unknown[]) {
const validFunctions = functions.filter(isFunction) as Function[]
if (validFunctions.length === 0) {
return (x: any) => x
}
return (x: any) => validFunctions.reduceRight((acc, fn) => fn(acc), x)
}
const addOne = (x: number) => x + 1
const double = (x: number) => x * 2
const square = (x: number) => x * x
const composed = compose(square, double, addOne, 'not a function')
console.log(composed(5)) // 144 (5 + 1 = 6, 6 * 2 = 12, 12 * 12 = 144)
Notes
- Function Types: Checks all types of functions (normal functions, arrow functions, async functions, generator functions)
- Constructor Functions: Constructor functions are also considered functions
- Classes: Classes themselves are functions (constructors)
- Type Guards: Serves as a TypeScript type guard
- Performance: Fast checking, suitable for high-frequency use
Differences from Other Methods
isFunction()
: Checks if value is a functiontypeof value === 'function'
: Native JavaScript checkvalue instanceof Function
: Checks if value is a Function instancevalue.constructor === Function
: Checks constructor
Practical Application Scenarios
- Event Handling: Validate event listeners
- Callback Functions: Validate callback parameters
- Plugin Systems: Validate plugin methods
- Middleware: Validate middleware functions
- API Design: Validate API callbacks
- Utility Functions: Validate utility function parameters