Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support specifying the type of all columns #34

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,22 @@ prefer strings, pass `--datesAsStrings`. Note that you'll be responsible for
making sure that timestamps/dates really do come back as strings, not Date objects.
See <https://github.com/brianc/node-pg-types> for details.

### JSON types
### Custom types

By default, Postgres `json` and `jsonb` columns will be typed as `unknown`.
This is safe but not very precise, and it can make them cumbersome to work with.
Oftentimes you know what the type should be.
Oftentimes you know what the type should be. Similarly, you may have text columns
that are really enums or contain template literal types.

To tell `pg-to-ts` to use a specific TypeScript type for a `json` column, use
a JSDoc `@type` annotation:

```sql
ALTER TABLE product ADD COLUMN metadata jsonb;
COMMENT ON COLUMN product.metadata is 'Additional information @type {ProductMetadata}';

ALTER TABLE product ADD COLUMN supplier_id text;
COMMENT ON COLUMN product.supplier_id is 'The supplier @type {SupplierId}';
```

On its own, this simply acts as documentation. But if you also specify the
Expand All @@ -112,21 +116,23 @@ On its own, this simply acts as documentation. But if you also specify the
Then your `dbschema.ts` will look like:

```ts
import {ProductMetadata} from './db-types';
import {ProductMetadata,SupplierId} from './db-types';

interface Product {
id: string;
name: string;
description: string;
created_at: Date;
metadata: ProductMetadata | null;
supplier_id: SupplierId | null;
}
```

Presumably your `db-types.ts` file will either re-export this type from elsewhere:

```ts
export {ProductMetadata} from './path/to/this-type';
export {SupplierId} from './path/to/this-type';
```

or define it itself:
Expand All @@ -137,12 +143,12 @@ export interface ProductMetadata {
designer?: string;
starRating?: number;
}
type SupplierId = `sup_${string}`;
```

Note that, on its own, TypeScript cannot enforce a schema on your `json`
columns. For that, you'll want a tool like [postgres-json-schema][].


### Prefix tableNames with their corresponding schemaName

`--prefixWithSchemaNames`
Expand Down
2 changes: 1 addition & 1 deletion src/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export function generateTableInterface(
jsdoc = comment ? `/** ${comment} */\n` : '';

let {tsType} = columnDef;
if (tsType === 'Json' && options.options.jsonTypesFile && comment) {
if (options.options.jsonTypesFile && comment) {
const m = JSDOC_TYPE_RE.exec(comment);
if (m) {
tsType = m[1].trim();
Expand Down
3 changes: 3 additions & 0 deletions test/fixture/pg-to-ts.sql
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,8 @@ COMMENT ON COLUMN comment.metadata IS 'Additional comment info @type {CommentMet
COMMENT ON COLUMN comment.statuses IS 'List of statuses; Just an array for testing!';

CREATE TABLE IF NOT EXISTS table_with_underscores (
id text not null PRIMARY KEY,
column_with_underscores text not null
);

COMMENT ON COLUMN table_with_underscores.id IS 'Table ID has @type {TableId}';
34 changes: 23 additions & 11 deletions test/integration/__snapshots__/integration.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ exports[`Integration tests Schema generation pg-to-sql features 1`] = `
"/* tslint:disable */
/* eslint-disable */

import { CommentMetadata } from \\"./pg-to-ts-json-types\\";
import { CommentMetadata, TableId } from \\"./pg-to-ts-json-types\\";


export type Json = unknown;
Expand Down Expand Up @@ -397,16 +397,20 @@ const doc = {

// Table table_with_underscores
export interface TableWithUnderscores {
/** Table ID has @type {TableId} */
id: TableId;
column_with_underscores: string;
}
export interface TableWithUnderscoresInput {
/** Table ID has @type {TableId} */
id: TableId;
column_with_underscores: string;
}
const table_with_underscores = {
tableName: 'table_with_underscores',
columns: ['column_with_underscores'],
requiredForInsert: ['column_with_underscores'],
primaryKey: null,
columns: ['id', 'column_with_underscores'],
requiredForInsert: ['id', 'column_with_underscores'],
primaryKey: 'id',
foreignKeys: {},
$type: null as unknown as TableWithUnderscores,
$input: null as unknown as TableWithUnderscoresInput
Expand Down Expand Up @@ -466,7 +470,7 @@ exports[`Integration tests Schema generation pg-to-sql with camelCase 1`] = `
"/* tslint:disable */
/* eslint-disable */

import { CommentMetadata } from \\"./pg-to-ts-json-types\\";
import { CommentMetadata, TableId } from \\"./pg-to-ts-json-types\\";


export type Json = unknown;
Expand Down Expand Up @@ -539,16 +543,20 @@ const public_doc = {

// Table public.table_with_underscores
export interface PublicTableWithUnderscores {
/** Table ID has @type {TableId} */
id: TableId;
columnWithUnderscores: string;
}
export interface PublicTableWithUnderscoresInput {
/** Table ID has @type {TableId} */
id: TableId;
columnWithUnderscores: string;
}
const public_table_with_underscores = {
tableName: 'public.table_with_underscores',
columns: ['columnWithUnderscores'],
requiredForInsert: ['columnWithUnderscores'],
primaryKey: null,
columns: ['id', 'columnWithUnderscores'],
requiredForInsert: ['id', 'columnWithUnderscores'],
primaryKey: 'id',
foreignKeys: {},
$type: null as unknown as PublicTableWithUnderscores,
$input: null as unknown as PublicTableWithUnderscoresInput
Expand Down Expand Up @@ -635,16 +643,20 @@ const public_users = {

// Table public.table_with_underscores
export interface PublicTableWithUnderscores {
/** Table ID has @type {TableId} */
id: string;
column_with_underscores: string;
}
export interface PublicTableWithUnderscoresInput {
/** Table ID has @type {TableId} */
id: string;
column_with_underscores: string;
}
const public_table_with_underscores = {
tableName: 'public.table_with_underscores',
columns: ['column_with_underscores'],
requiredForInsert: ['column_with_underscores'],
primaryKey: null,
columns: ['id', 'column_with_underscores'],
requiredForInsert: ['id', 'column_with_underscores'],
primaryKey: 'id',
foreignKeys: {},
$type: null as unknown as PublicTableWithUnderscores,
$input: null as unknown as PublicTableWithUnderscoresInput
Expand Down