refactor(types): 消除非必要 as 逃逸,锁紧 strict 政策

按 Oracle 复核处置全仓 5 处类型断言:

- fields.ts: as const → satisfies Record<GeneratedFieldKey, true>
- compile.ts: as readonly string[] → ReadonlySet<string>.has()
- embed-migrations.ts: JSON.parse as Journal → Zod schema 运行时校验,JSON.parse 显式 unknown
- interceptors.ts: 唯一保留的跨包断言(ORPC→Zod)注释扩写为完整背景
- router.tsx: satisfies 非 cast,保留

biome.json 增配 noExplicitAny / noTsIgnore / noNonNullAssertion,防止后续漂移。
This commit is contained in:
2026-04-25 14:23:08 +08:00
parent f520b54ca5
commit 695e826dcf
5 changed files with 38 additions and 9 deletions
+7
View File
@@ -24,6 +24,13 @@
}, },
"correctness": { "correctness": {
"noReactPropAssignments": "error" "noReactPropAssignments": "error"
},
"style": {
"noNonNullAssertion": "error"
},
"suspicious": {
"noExplicitAny": "error",
"noTsIgnore": "error"
} }
} }
}, },
+3 -2
View File
@@ -12,8 +12,9 @@ const SUPPORTED_TARGETS: readonly Bun.Build.CompileTarget[] = [
'bun-linux-arm64', 'bun-linux-arm64',
] ]
const isSupportedTarget = (value: string): value is Bun.Build.CompileTarget => const SUPPORTED_TARGET_SET: ReadonlySet<string> = new Set(SUPPORTED_TARGETS)
(SUPPORTED_TARGETS as readonly string[]).includes(value)
const isSupportedTarget = (value: string): value is Bun.Build.CompileTarget => SUPPORTED_TARGET_SET.has(value)
const { values } = parseArgs({ const { values } = parseArgs({
options: { target: { type: 'string' } }, options: { target: { type: 'string' } },
+19 -5
View File
@@ -1,17 +1,31 @@
import { existsSync } from 'node:fs' import { existsSync } from 'node:fs'
import { readFile, writeFile } from 'node:fs/promises' import { readFile, writeFile } from 'node:fs/promises'
import { z } from 'zod'
const JOURNAL = './drizzle/meta/_journal.json' const JOURNAL = './drizzle/meta/_journal.json'
const OUTPUT = './src/server/db/migrations.gen.ts' const OUTPUT = './src/server/db/migrations.gen.ts'
const SQL_RELATIVE_FROM_OUTPUT = '../../../drizzle' const SQL_RELATIVE_FROM_OUTPUT = '../../../drizzle'
type JournalEntry = { idx: number; tag: string; when: number; breakpoints: boolean } const journalEntrySchema = z.object({
type Journal = { entries: JournalEntry[] } idx: z.number(),
tag: z.string(),
when: z.number(),
breakpoints: z.boolean(),
})
const journalSchema = z.object({ entries: z.array(journalEntrySchema).default([]) })
type JournalEntry = z.infer<typeof journalEntrySchema>
const readJournalEntries = async (): Promise<JournalEntry[]> => {
if (!existsSync(JOURNAL)) {
return []
}
const raw: unknown = JSON.parse(await readFile(JOURNAL, 'utf-8'))
return journalSchema.parse(raw).entries.sort((a, b) => a.idx - b.idx)
}
const main = async () => { const main = async () => {
const entries: JournalEntry[] = existsSync(JOURNAL) const entries = await readJournalEntries()
? ((JSON.parse(await readFile(JOURNAL, 'utf-8')) as Journal).entries ?? []).sort((a, b) => a.idx - b.idx)
: []
const imports = entries const imports = entries
.map((e) => `import sql_${e.idx} from '${SQL_RELATIVE_FROM_OUTPUT}/${e.tag}.sql' with { type: 'text' }`) .map((e) => `import sql_${e.idx} from '${SQL_RELATIVE_FROM_OUTPUT}/${e.tag}.sql' with { type: 'text' }`)
+2 -1
View File
@@ -8,7 +8,8 @@ export const logError = (error: unknown) => {
export const handleValidationError = (error: unknown) => { export const handleValidationError = (error: unknown) => {
if (error instanceof ORPCError && error.code === 'BAD_REQUEST' && error.cause instanceof ValidationError) { if (error instanceof ORPCError && error.code === 'BAD_REQUEST' && error.cause instanceof ValidationError) {
// ORPC ValidationError.issues are Zod issues in this app. // ORPC widens issues to the Standard Schema shape; every contract here is built from Zod/drizzle-zod,
// so the runtime objects are Zod issues. Rehydrate to reuse z.prettifyError / z.flattenError.
const zodError = new z.ZodError(error.cause.issues as z.core.$ZodIssue[]) const zodError = new z.ZodError(error.cause.issues as z.core.$ZodIssue[])
throw new ORPCError('INPUT_VALIDATION_FAILED', { throw new ORPCError('INPUT_VALIDATION_FAILED', {
+7 -1
View File
@@ -12,4 +12,10 @@ export const generatedFields = {
.$onUpdateFn(() => new Date()), .$onUpdateFn(() => new Date()),
} }
export const generatedFieldKeys = { id: true, createdAt: true, updatedAt: true } as const type GeneratedFieldKey = keyof typeof generatedFields
export const generatedFieldKeys = {
id: true,
createdAt: true,
updatedAt: true,
} satisfies Record<GeneratedFieldKey, true>