Skip to content

Commit

Permalink
add lazy function
Browse files Browse the repository at this point in the history
  • Loading branch information
andrej-dyck committed Dec 16, 2023
1 parent dd65532 commit d9bdc5b
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 0 deletions.
1 change: 1 addition & 0 deletions index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './lazy/index.js'
17 changes: 17 additions & 0 deletions lazy/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* A lazy function for typescript projects.
*/
export const lazy = <T>(create: () => T) => {
let instance: T | undefined = undefined
return (): T => instance ??= create()
}

/*
* Example:
* const config = lazy(
* () => fs.readFileSync('config.json').then(f => cfgSchema.parse(f))
* )
*
* config().PROP_1
* config().PROP_2 // config file is read and parsed only once
*/
45 changes: 45 additions & 0 deletions lazy/lazy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { expect, test } from 'vitest'
import { lazy } from './index.js'

test('lazy remembers the value of its function', () => {
const lazyValue = lazy(() => 1)

expect(lazyValue()).toBe(1)
})

test('lazy executes its function only once', () => {
let countExecutions = 0

const lazyValue = lazy(() => {
countExecutions++
return 1
})

lazyValue()
lazyValue()

expect(countExecutions).toBe(1)
})

test('lazy does propagate exceptions on first use', () => {
const lazyValue = lazy(() => {
throw new Error()
})

expect(lazyValue).toThrowError()
})

test('lazy retries on exceptions', () => {
let countExecutions = 0

const lazyValue = lazy(() => {
if (countExecutions === 0) {
countExecutions++
throw new Error()
}
return 1
})

expect(lazyValue).toThrowError()
expect(lazyValue()).toBe(1)
})

0 comments on commit d9bdc5b

Please sign in to comment.