mirror of
https://github.com/go-admin-team/go-admin.git
synced 2026-09-23 10:51:09 +00:00
fix🐛: query-less table's Query type broke FK dropdown fetches (P0)
3625ce8 fixed the no-empty-object-type lint error by switching a
zero-IsQuery table's {ClassName}Query to `Record<string, never>`, the
same default useTable.ts's own `TQuery extends object = Record<string,
never>` uses. That default is safe there only because useTable.ts's one
internal `TQuery & PageQuery` goes through an `as` cast rather than a
structural check. Code that builds the object literal directly does not
get that protection - and vue.go.template's foreign-key dropdown fetch
does exactly that: `list{FkClass}({ pageIndex: 1, pageSize: 100 })`.
Record<string, never> is a mapped type over every string key, each
mapped to never, so `Record<string, never> & PageQuery` does not leave
PageQuery's own properties alone: pageIndex becomes `never & number`,
i.e. never, and no value can be passed for it - a straight type error,
not a lint warning, so the previous fix's pnpm lint pass did not catch
it. Trips on any query-less table referenced by a foreign key - a plain
lookup/dict table used as a dropdown source, an ordinary shape, not a
rare one.
Switched to Record<never, never>: a mapped type over the empty key
set, which behaves as the empty object type `{}` under intersection
(PageQuery's properties come through unchanged) while still satisfying
`TQuery extends object` and not tripping no-empty-object-type (it is a
generic instantiation, not a literal `{}` type annotation) - confirmed
all three separately before touching the template.
Verified with node 24.11.0: generated a real zero-IsQuery table, copied
its .ts into go-admin-ui alongside a throwaway file reproducing
vue.go.template's exact FK call site
(`await list{Class}({ pageIndex: 1, pageSize: 100 })`), and ran both
eslint and vue-tsc --noEmit - the type-check step lint alone cannot
cover, which is what let this through the first time. Confirmed red
first (swapped the generated file's Record<never, never> back to
Record<string, never>): vue-tsc reported the exact "Property 'pageIndex'
is incompatible with index signature" error. Restored the fix - both
clean.
This commit is contained in:
@@ -58,12 +58,31 @@ export interface {{.ClassName}}Query {
|
||||
`export interface {ClassName}Query {}` is what naturally falls out of the
|
||||
range above finding nothing to iterate, but an empty interface trips
|
||||
@typescript-eslint/no-empty-object-type and fails pnpm lint.
|
||||
Record<string, never> is go-admin-ui's own answer to the same shape -
|
||||
see composables/useTable.ts's `TQuery extends object = Record<string, never>`
|
||||
- and it intersects with PageQuery the same way an empty interface would
|
||||
have, so callers do not have to special-case a query-less table.
|
||||
|
||||
Record<string, never> (this file's first attempt, and the type
|
||||
useTable.ts's own `TQuery extends object = Record<string, never>` default
|
||||
uses) looks like the obvious match but is wrong here: it is a mapped type
|
||||
over *every* string key, each mapped to never, so intersecting it with
|
||||
PageQuery does not leave PageQuery alone - `pageIndex` becomes
|
||||
`never & number`, i.e. never, and no value can be passed for it at all.
|
||||
useTable.ts itself never hits this because its one internal use of
|
||||
`TQuery & PageQuery` goes through an `as` cast rather than a structural
|
||||
check (composables/useTable.ts ~line 160); code that builds the object
|
||||
literal directly - such as a foreign-key column's
|
||||
`list{FkClass}({ pageIndex: 1, pageSize: 100 })` call in vue.go.template -
|
||||
is not casting anything and hits the real error, only when the referenced
|
||||
table happens to have no query columns of its own (a plain lookup/dict
|
||||
table used as a dropdown source, not a rare shape).
|
||||
|
||||
Record<never, never> is the type with the same intent - "no query
|
||||
columns" - but the mapped-type domain is `never`, so it has no keys at
|
||||
all rather than "every key, mapped to never": it behaves as the empty
|
||||
object type `{}` under intersection, leaving PageQuery's own pageIndex/
|
||||
pageSize untouched, and confirmed separately not to trip
|
||||
no-empty-object-type either (it is a generic instantiation, not a
|
||||
literal `{}` type annotation).
|
||||
*/ -}}
|
||||
export type {{.ClassName}}Query = Record<string, never>
|
||||
export type {{.ClassName}}Query = Record<never, never>
|
||||
{{- end}}
|
||||
|
||||
export function list{{.ClassName}}(query: {{.ClassName}}Query & PageQuery) {
|
||||
|
||||
Reference in New Issue
Block a user