Item 58: Consider Codegen as an Alternative to Complex Types
May 10, 2024 ยท View on GitHub
Things to Remember
- 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 diffon your continuous integration system to make sure generated code stays in sync.## Code Samples
async function getBooks(db: Database) {
const result = await db.query(
`SELECT title, author, year, publisher FROM books`
);
return result.rows;
}
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;
}
// 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;
}
// 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;
}
// 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;
}