evlog version
2.19.1
Runtime & OS
Node 24.13.0, macOS
Framework / integration
All integrations (Hono shown below, but Next.js, Nitro, Nuxt, SvelteKit, Elysia, Express, Fastify are all affected identically).
Adapter or drain (optional)
N/A — compile-time typing issue.
Description
createRequestLogger() returns AuditableLogger<T>, where audit is required (packages/evlog/src/logger.ts:1028, audit.ts:180). But the loggers that integrations expose to user code — useLogger() and per-request context vars — are typed as RequestLogger<T>, where audit is optional (types.ts:761). The runtime value is always the AuditableLogger, so .audit is in fact always present, yet TypeScript infers it as possibly undefined.
Affected surfaces (all typed RequestLogger): Hono EvlogVariables (hono/index.ts:23), and useLogger() for Next.js (next/storage.ts:21), Nitro (nitro-v3/useLogger.ts:20), generic server (runtime/server/useLogger.ts:35), Elysia (elysia/index.ts:32), Express/Fastify (shared/storage.ts:16), plus Request.log (express/index.ts:16) and H3EventContext.log (types.ts:923).
Expected behavior
The logger exposed via useLogger() / c.get('log') / req.log / event.context.log should be typed as AuditableLogger<T>, so .audit(…) type-checks without optional chaining or !.
Actual behavior
audit is inferred as optional, so calling it errors:
const log = c.get('log') // typed RequestLogger
log.audit({ action: 'users.list', outcome: 'success' })
// ~~~~~ Cannot invoke an object which is possibly 'undefined'. ts(2722)
Workaround required today: log.audit?.(…) or log.audit!(…).
Reproduction
import { Hono } from 'hono'
import { evlog, type EvlogVariables } from 'evlog/hono'
const app = new Hono<EvlogVariables>()
app.use(evlog())
app.get('/api/users', (c) => {
const log = c.get('log')
log.audit({ action: 'users.list', outcome: 'success' }) // ❌ ts(2722)
return c.json({ users: [] })
})
evlog version
2.19.1
Runtime & OS
Node 24.13.0, macOS
Framework / integration
All integrations (Hono shown below, but Next.js, Nitro, Nuxt, SvelteKit, Elysia, Express, Fastify are all affected identically).
Adapter or drain (optional)
N/A — compile-time typing issue.
Description
createRequestLogger()returnsAuditableLogger<T>, whereauditis required (packages/evlog/src/logger.ts:1028,audit.ts:180). But the loggers that integrations expose to user code —useLogger()and per-request context vars — are typed asRequestLogger<T>, whereauditis optional (types.ts:761). The runtime value is always theAuditableLogger, so.auditis in fact always present, yet TypeScript infers it as possiblyundefined.Affected surfaces (all typed
RequestLogger): HonoEvlogVariables(hono/index.ts:23), anduseLogger()for Next.js (next/storage.ts:21), Nitro (nitro-v3/useLogger.ts:20), generic server (runtime/server/useLogger.ts:35), Elysia (elysia/index.ts:32), Express/Fastify (shared/storage.ts:16), plusRequest.log(express/index.ts:16) andH3EventContext.log(types.ts:923).Expected behavior
The logger exposed via
useLogger()/c.get('log')/req.log/event.context.logshould be typed asAuditableLogger<T>, so.audit(…)type-checks without optional chaining or!.Actual behavior
auditis inferred as optional, so calling it errors:Workaround required today:
log.audit?.(…)orlog.audit!(…).Reproduction