From 3625ce851b11f7bd70f24158521917593b3be198 Mon Sep 17 00:00:00 2001 From: zhangwenjian Date: Sat, 19 Sep 2026 20:36:24 +0800 Subject: [PATCH] =?UTF-8?q?fix=F0=9F=90=9B:=20empty=20Query=20interface=20?= =?UTF-8?q?for=20zero-IsQuery=20tables=20trips=20no-empty-object-type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A plain display table with no search form (zero columns marked IsQuery=1) is a normal shape, not an edge case - but ts.go.template's Query interface only had a body when the range over .Columns found a match, so it rendered `export interface {ClassName}Query {}`, which @typescript-eslint/no-empty-object-type flags and pnpm lint fails on. Falls back to `export type {ClassName}Query = Record` when no column qualifies - the same answer go-admin-ui's own useTable.ts already gives this shape (`TQuery extends object = Record`), so it intersects with PageQuery the same way an empty interface would have and callers do not need to special-case a query-less table. Audited the rest of this template for the same "zero of some optional feature" shape while in here, since this is the third time a query-less/ select-less/whatever-less table has slipped through (dictLabel, DateCell, this one): - a zero-column table: cannot occur - a table without at least a primary key column cannot exist to be imported from information_schema in the first place, so .Columns is never empty here. - a table with only its primary key column: the row interface still has one property (the pk); not empty, no lint issue. - a table where every column has IsInsert=0: does not affect this template - add{Class}/update{Class} both take the full row interface unconditionally (every column, not just IsInsert ones), so there is no column-count-dependent shape to go empty here. Verified with node 24.11.0 (not the machine default): generated a zero-IsQuery table and a with-IsQuery table, copied both into go-admin-ui and ran eslint + vue-tsc --noEmit. Confirmed red first - `export interface VerifyNoQueryQuery {}` failed eslint with exactly the no-empty-object-type error. Restored the fix - clean on both, plus a throwaway call site instantiating useTable to prove the type satisfies useTable's `TQuery extends object` constraint, not just that it parses in isolation. --- template/v4/ts.go.template | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/template/v4/ts.go.template b/template/v4/ts.go.template index 7b1ed598..4387eff1 100644 --- a/template/v4/ts.go.template +++ b/template/v4/ts.go.template @@ -8,8 +8,10 @@ TS compile error at the call site, not a runtime bug. */ -}} {{- $pkType := "number" -}} +{{- $hasQuery := false -}} {{- range .Columns -}} {{- if and .Pk (eq .GoType "string") }}{{$pkType = "string"}}{{end -}} + {{- if eq .IsQuery "1" }}{{$hasQuery = true}}{{end -}} {{- end -}} import request from '@/utils/request' import type { ApiResponse, PageQuery, PageResult, Id } from '@/types/api' @@ -30,6 +32,7 @@ export interface {{.ClassName}} { {{- end}} } +{{if $hasQuery -}} export interface {{.ClassName}}Query { {{- range .Columns}} {{- if eq .IsQuery "1"}} @@ -47,6 +50,21 @@ export interface {{.ClassName}}Query { {{- end}} {{- end}} } +{{- else -}} +{{- /* + No column is marked IsQuery - a plain display table with no search form + is a normal shape, not an edge case, so this still has to produce a type + useTable/list{ClassName}(query: Query & PageQuery) can use. + `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 is go-admin-ui's own answer to the same shape - + see composables/useTable.ts's `TQuery extends object = Record` + - 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. +*/ -}} +export type {{.ClassName}}Query = Record +{{- end}} export function list{{.ClassName}}(query: {{.ClassName}}Query & PageQuery) { return request>>({