prisma
prisma copied to clipboard
fix(client): type inference for `prismaClient.$on(...)`
Problem
- incorrect inference in generic
GetLogType
returnednever
instead ofT
on line 6. (original piece of code here)
/*1.*/export type GetLogType<T extends LogLevel | LogDefinition> =
/*2.*/ T extends LogDefinition
/*3.*/ ? T['emit'] extends 'event'
/*4.*/ ? T['level']
/*5.*/ : never
/*6.*/ : never
This code led to error when some of the elements in T
argument of GetEvents
which are being later passed to GetLogType
were LogLevel
string literals instead of LogDefinition
objects.
- Case when developer forgot to add
as const
(and there's no suggestion in documentation to add it) to the argument ofPrismaClient
constructor.
const prisma = new PrismaClient({
log: ['query', 'info', 'warn', 'error'],
})
Since neither developer, nor PrismaClient
generic itself (const
before U
is absent here) didn't tell typescript to treat argument of new PrismaClient(...)
as constant, the type information of string literals will be erased and typescript will handle it just as { log: string[] }
.
-
GetEvents
was hardcoded to expect arrays with length at max 4-elements here
Solution
-
GetLogType
now returns those literals as is when they don't extendLogDefinition
(object), but also with additional check which then forcesT
ofGetLogType<T>
to extendLogLevel
- Added useful
const
modifier to the secondU
argument ofPrismaClient
generic which preserves string literal type info taken from the argument ofPrismaClient
constructor -
GetEvents
generic is now a recursive type and doesn't depend on length ofPrismaClientOptions.log
array
Might fix some of the following issues:
- https://github.com/prisma/prisma/issues/19463
- https://github.com/prisma/docs/issues/5021
- https://github.com/prisma/docs/issues/1564
- https://github.com/prisma/prisma/issues/4746
- https://github.com/prisma/prisma/issues/7068
- https://github.com/notiz-dev/nestjs-prisma/issues/56
- https://github.com/prisma/prisma/issues/11986
- https://github.com/prisma/prisma/issues/6279
- https://github.com/prisma/docs/issues/3424
Before
U
argument of PrismaClient
generic is never
mainly because of the 1st problem mentioned above and we can't call prismaClient.$on(...)
passing any string literal to it:
After
The 1st screenshot shows that the second inferred argument U
of generic PrismaClient
stored in DB
constant is now "info" | "query" | "error"
according to IDE's tooltip above the line DB.$on('', () => {})
and typescript also tells to replace first argument ''
to any of U
union members:
2nd screenshot shows that when we pass correct 1st argument to DB.$on
it correctly infers type of the 2nd function argument:
CodSpeed Performance Report
Merging #24133 will not alter performance
Comparing nikelborm:main
(06709d7) with main
(7aae7ec)
Summary
✅ 3
untouched benchmarks
Any updates or progress on this? Are we able to get this merged?
Running into this issue when attempting to customise the prismaClient
event logging.
Any updates or progress on this? Are we able to get this merged? Running into this issue when attempting to customise the
prismaClient
event logging.
I honestly have no idea why this wasn't merged. I came back here few times already to pull upstream, patiently waiting for a response or review. Haven't got any in almost half of the year.