How to type a function with column key of table

I can't get this to type correctly. I want field to be a column of table, but typescript keeps saying Type 'Field' cannot be used to index type 'TTable'. What's the best way to do this?
type GetColumnKeys<TTable extends Table> = keyof {
[K in keyof TTable as K extends keyof TTable['_']['columns'] ? K : never]: true
}

async function getOptions<
TTable extends Table,
Field extends GetColumnKeys<TTable>
>(table: TTable, field: Field) {
const column = table[field]
const result = await drizzleDb
.selectDistinct({
option: column
})
.from(table)
.orderBy(column)
return result.map((i) => String(i.option))
}
type GetColumnKeys<TTable extends Table> = keyof {
[K in keyof TTable as K extends keyof TTable['_']['columns'] ? K : never]: true
}

async function getOptions<
TTable extends Table,
Field extends GetColumnKeys<TTable>
>(table: TTable, field: Field) {
const column = table[field]
const result = await drizzleDb
.selectDistinct({
option: column
})
.from(table)
.orderBy(column)
return result.map((i) => String(i.option))
}
5 Replies
Angelelz
Angelelz11mo ago
How about:
Field extends keyof TTable & string
Field extends keyof TTable & string
JustTheSyme
JustTheSymeOP11mo ago
@Angelelz I get an error trying to pass column to option with that:
1. Type 'TTable[Field]' is not assignable to type 'SQL<unknown> | Aliased<unknown> | PgColumn<ColumnBaseConfig<ColumnDataType, string>, {}, {}> | PgTable<TableConfig> | SelectedFieldsFlat<...>'.
Type 'TTable[keyof TTable & string]' is not assignable to type 'SQL<unknown> | Aliased<unknown> | PgColumn<ColumnBaseConfig<ColumnDataType, string>, {}, {}> | PgTable<TableConfig> | SelectedFieldsFlat<...>'.
Type 'TTable[string]' is not assignable to type 'SQL<unknown> | Aliased<unknown> | PgColumn<ColumnBaseConfig<ColumnDataType, string>, {}, {}> | PgTable<TableConfig> | SelectedFieldsFlat<...>'.
Type 'TTable[string]' is not assignable to type 'PgTable<TableConfig>'.
Type 'TTable[keyof TTable & string]' is not assignable to type 'PgTable<TableConfig>'.
Type 'TTable[Field]' is not assignable to type 'PgTable<TableConfig>'.
Type 'TTable[keyof TTable & string]' is not assignable to type 'PgTable<TableConfig>'.
Type 'TTable[string]' is not assignable to type 'PgTable<TableConfig>'. [2322]
1. Type 'TTable[Field]' is not assignable to type 'SQL<unknown> | Aliased<unknown> | PgColumn<ColumnBaseConfig<ColumnDataType, string>, {}, {}> | PgTable<TableConfig> | SelectedFieldsFlat<...>'.
Type 'TTable[keyof TTable & string]' is not assignable to type 'SQL<unknown> | Aliased<unknown> | PgColumn<ColumnBaseConfig<ColumnDataType, string>, {}, {}> | PgTable<TableConfig> | SelectedFieldsFlat<...>'.
Type 'TTable[string]' is not assignable to type 'SQL<unknown> | Aliased<unknown> | PgColumn<ColumnBaseConfig<ColumnDataType, string>, {}, {}> | PgTable<TableConfig> | SelectedFieldsFlat<...>'.
Type 'TTable[string]' is not assignable to type 'PgTable<TableConfig>'.
Type 'TTable[keyof TTable & string]' is not assignable to type 'PgTable<TableConfig>'.
Type 'TTable[Field]' is not assignable to type 'PgTable<TableConfig>'.
Type 'TTable[keyof TTable & string]' is not assignable to type 'PgTable<TableConfig>'.
Type 'TTable[string]' is not assignable to type 'PgTable<TableConfig>'. [2322]
Angelelz
Angelelz11mo ago
I would just cast it and call it a day:
const column = table[field] as AnyPgColumn
const column = table[field] as AnyPgColumn
JustTheSyme
JustTheSymeOP11mo ago
@Angelelz I found that this works fine with typesafety
async function getOptions<
TTable extends Table,
Field extends keyof TTable['_']['columns']
>(table: TTable, field: Field) {
const columns = getTableColumns(table)
const column = columns[field]
if (!column) {
return []
}
const result = await drizzleDb
.selectDistinct({
option: column
})
.from(table)
.orderBy(column)
return result.map((i) => String(i.option))
}
async function getOptions<
TTable extends Table,
Field extends keyof TTable['_']['columns']
>(table: TTable, field: Field) {
const columns = getTableColumns(table)
const column = columns[field]
if (!column) {
return []
}
const result = await drizzleDb
.selectDistinct({
option: column
})
.from(table)
.orderBy(column)
return result.map((i) => String(i.option))
}
But I wish I didn't have to make a call to getTableColumns to make it work. It's not too bad, though.
Angelelz
Angelelz11mo ago
This is a great idea! I don't see too many downsides to this
Want results from more Discord servers?
Add your server