Item 58: Consider Codegen as an Alternative to Complex Types
要点
- While type-level TypeScript is an impressively powerful tool, it's not always the best tool for the job.
- For complex type manipulations, consider generating code and types as an alternative to writing type-level code. Your code generation tool can be written in ordinary TypeScript or any other language.
- Run codegen and
git diff
on your continuous integration system to make sure generated code stays in sync. - 虽然 TypeScript 的类型层次非常强大,但并不总是最适合的工具。
- 对于复杂的类型操作,考虑生成代码和类型作为写类型层次代码的替代方案。你的代码生成工具可以用普通的 TypeScript 或其他语言编写。
- 在持续集成系统上运行代码生成和
git diff
,以确保生成的代码与源代码保持同步。
正文
ts
async function getBooks(db: Database) {
const result = await db.query(
`SELECT title, author, year, publisher FROM books`
)
return result.rows
}
ts
async function getLatestBookByAuthor(db: Database, publisher: string) {
const result = await db.query(
`SELECT author, MAX(year) FROM books GROUP BY author WHERE publisher=$1`,
[publisher]
)
return result.rows
}
ts
// books-queries.ts
import { sql } from '@pgtyped/runtime'
const selectLatest = sql`
SELECT author, MAX(year)
FROM books
GROUP BY author
WHERE publisher=$publisher
`
async function getLatestBookByAuthor(db: Database, publisher: string) {
const result = await selectLatest.run({ publisher }, db)
// ^? const result: any[]
return result
}
ts
// books-queries.types.ts
/** Types generated for queries found in "books-queries.ts" */
/** 'selectLatest' parameters type */
export interface selectLatestParams {
publisher: string
}
/** 'selectLatest' return type */
export interface selectLatestResult {
author: string
year: number
}
/** 'selectLatest' query type */
export interface selectLatestQuery {
params: selectLatestParams
result: selectLatestResult
}
ts
// books-queries.ts
import { sql } from '@pgtyped/runtime'
import { selectLatestQuery } from './books-queries.types'
export const selectLatestBookByAuthor = sql<selectLatestQuery>`
SELECT author, MAX(year)
FROM books
GROUP BY author
WHERE publisher=$publisher
`
async function getLatestBookByAuthor(db: Database, publisher: string) {
const result = await selectLatestBookByAuthor.run({ publisher }, db)
// ^? const result: selectLatestResult[]
return result
}