Utils
Essential Kotlin-style utility functions for everyday TypeScript development
Overview
The utils module provides common Kotlin standard library functions adapted for TypeScript. These utilities help with control flow, validation, error handling, lazy initialization, and functional programming patterns.
Control Flow
Repeat operations and loop control
import { repeat, repeatAsync } from 'kotlinify-ts'
// Execute action n times (sync)
repeat(5, (index) => {
console.log(`Iteration ${index}`)
})
// Prints: Iteration 0, 1, 2, 3, 4
// Execute async action n times
await repeatAsync(3, async (index) => {
await someAsyncOperation(index)
})Runtime Validation
Require and check with type narrowing
import { require, check, requireNotNull, checkNotNull } from 'kotlinify-ts'
function processAge(age: number) {
// Throws if condition is false
require(age >= 0, 'Age must be non-negative')
require(age < 150, () => `Age ${age} is unrealistic`)
// TypeScript knows age is valid here
return age * 365
}
function processUser(user: User | null) {
// Returns non-null or throws
const validUser = requireNotNull(user, 'User is required')
// TypeScript knows validUser is User (not null)
return validUser.name
}
// check is similar to require
function validateConfig(config: Config) {
check(config.port > 0, 'Port must be positive')
check(config.timeout > 0, 'Timeout must be positive')
}Error Handling
Catch exceptions safely
import { runCatching, runCatchingAsync, TODO } from 'kotlinify-ts'
// Catch exceptions and return result object
const result = runCatching(() => {
return riskyOperation()
})
if (result.success) {
console.log('Value:', result.value)
} else {
console.error('Error:', result.error)
}
// Async version
const asyncResult = await runCatchingAsync(async () => {
return await fetchData()
})
// Mark unimplemented code
function futureFeature() {
TODO('Implement this feature')
// Throws: Error: Not implemented: Implement this feature
}Lazy Initialization
Compute values only when needed
import { lazy } from 'kotlinify-ts'
// Create lazy value (computed on first access)
const expensiveConfig = lazy(() => {
console.log('Computing config...')
return loadConfigFromFile()
})
// Not computed yet
console.log('Before access')
// Computed now (prints "Computing config...")
const config1 = expensiveConfig()
// Uses cached value (doesn't print again)
const config2 = expensiveConfig()
console.log(config1 === config2) // truePerformance Measurement
Measure execution time
import { measure, measureSync } from 'kotlinify-ts'
// Measure async function
const { value, duration } = await measure(async () => {
await heavyComputation()
return 'result'
})
console.log(`Completed in ${duration}ms`)
console.log(`Result: ${value}`)
// Measure sync function
const result = measureSync(() => {
let sum = 0
for (let i = 0; i < 1000000; i++) {
sum += i
}
return sum
})
console.log(`Sum: ${result.value}, Time: ${result.duration}ms`)Functional Utilities
Common functional programming helpers
import { identity, constant, noop } from 'kotlinify-ts'
// Identity function (returns input)
const numbers = [1, 2, 3].map(identity) // [1, 2, 3]
// Constant function (always returns same value)
const getDefault = constant(42)
getDefault() // 42
getDefault() // 42
// No-op function (does nothing)
const cleanup = shouldCleanup ? doCleanup : noop
cleanup() // Safe to callAssertions
Development-time checks
import { assert, assertNotNull, error } from 'kotlinify-ts'
function processData(data: unknown[]) {
// Development assertion
assert(data.length > 0, 'Data should not be empty')
const first = data[0]
const value = assertNotNull(first, 'First element should exist')
// TypeScript knows value is non-null here
return value
}
function handleInvalidState(state: string): never {
switch (state) {
case 'valid':
return processValid()
case 'pending':
return processPending()
default:
// Throw error with message
error(`Invalid state: ${state}`)
}
}Real-World Examples
Configuration Loading
import { lazy, requireNotNull } from 'kotlinify-ts'
const getConfig = lazy(() => {
const env = process.env.NODE_ENV
requireNotNull(env, 'NODE_ENV must be set')
return {
apiUrl: requireNotNull(
process.env.API_URL,
'API_URL must be configured'
),
timeout: parseInt(process.env.TIMEOUT || '5000'),
env
}
})
// Config loaded only when first accessed
const config = getConfig()Input Validation
import { require, requireNotNull } from 'kotlinify-ts'
function createUser(data: {
name?: string
email?: string
age?: number
}) {
const name = requireNotNull(data.name, 'Name is required')
const email = requireNotNull(data.email, 'Email is required')
const age = requireNotNull(data.age, 'Age is required')
require(name.length >= 2, 'Name must be at least 2 characters')
require(email.includes('@'), 'Email must be valid')
require(age >= 18, 'Must be 18 or older')
return { name, email, age }
}Safe Computation
import { runCatching, measure } from 'kotlinify-ts'
async function processWithMetrics(data: unknown[]) {
const result = await measure(async () => {
return await runCatchingAsync(async () => {
return await heavyProcessing(data)
})
})
if (!result.value.success) {
console.error(`Processing failed in ${result.duration}ms`)
console.error('Error:', result.value.error)
return null
}
console.log(`Processed in ${result.duration}ms`)
return result.value.value
}Retry Logic with Utils
import { repeat, runCatchingAsync } from 'kotlinify-ts'
async function retryOperation(maxAttempts: number) {
let lastError: Error | undefined
await repeat(maxAttempts, async (attempt) => {
const result = await runCatchingAsync(async () => {
return await unstableOperation()
})
if (result.success) {
console.log('Success on attempt', attempt + 1)
return result.value
}
lastError = result.error
console.log(`Attempt ${attempt + 1} failed`)
})
if (lastError) {
throw lastError
}
}API Reference
repeat(times, action)Execute action n times synchronously
repeatAsync(times, action)Execute async action n times
require(condition, message?)Throw if condition is false (type narrowing)
check(condition, message?)Runtime check assertion
requireNotNull(value, message?)Return non-null value or throw (type narrowing)
checkNotNull(value, message?)Check non-null or throw
TODO(message?)Throw not-implemented error
todo(message?)Alias for TODO - marks unimplemented code
error(message)Throw error with message - useful for exhaustive checks
assert(condition, message?)Development assertion that throws if false
assertNotNull(value, message?)Assert value is non-null, return it with type narrowing
runCatching(block)Catch exceptions, return { success, value?, error? }
runCatchingAsync(block)Async version of runCatching
lazy(initializer)Lazy initialization with caching
measure(block)Measure execution time, return { value, duration }
measureSync(block)Sync version of measure
identity(value)Return input value unchanged
constant(value)Return function that always returns value
noop()No-operation function