Type Signature
type Insertable<R> = DrainOuterGeneric<
{
[K in NonNullableInsertKeys<R>]: InsertType<R[K]>
} & {
[K in NullableInsertKeys<R>]?: InsertType<R[K]>
}
>
Overview
Insertable<T> is a utility type that extracts the insert type from all columns in a table interface. It resolves the InsertType from any ColumnType definitions and creates a type representing what you can insert into the table.
Type Parameters
A table interface with column definitions.
Behavior
- Extracts the second type parameter (
InsertType) from each ColumnType<SelectType, InsertType, UpdateType>
- For regular types without
ColumnType, uses the type as-is
- Fields with nullable insert types (can be
undefined or null) become optional
- Fields with non-nullable insert types remain required
- Excludes columns where
InsertType is never
Examples
Basic Usage
import { Generated, ColumnType, Insertable } from 'kysely'
interface PersonTable {
id: Generated<number>
first_name: string
last_name: string
created_at: ColumnType<Date, string, never>
}
type InsertablePerson = Insertable<PersonTable>
// {
// id?: number
// first_name: string
// last_name: string
// created_at: string
// }
Notice:
id is optional (because Generated<number> allows undefined for inserts)
created_at is a string (not Date) for inserts
first_name and last_name are required strings
Using with Insert Queries
interface Database {
person: PersonTable
}
const db = new Kysely<Database>({ /* ... */ })
// Type-safe insert
const newPerson: InsertablePerson = {
first_name: 'John',
last_name: 'Doe',
created_at: '2024-01-01T00:00:00Z'
}
await db
.insertInto('person')
.values(newPerson)
.execute()
// Or inline
await db
.insertInto('person')
.values({
first_name: 'Jane',
last_name: 'Smith',
created_at: new Date().toISOString()
})
.execute()
With GeneratedAlways Columns
interface ProductTable {
id: GeneratedAlways<number>
name: string
price: number
created_at: Generated<Date>
}
type InsertableProduct = Insertable<ProductTable>
// {
// name: string
// price: number
// created_at?: Date
// }
// Note: id is excluded because GeneratedAlways has InsertType = never
Optional vs Required Fields
interface UserTable {
// Required fields (non-nullable insert type)
username: string
email: string
// Optional fields (nullable insert type)
id: Generated<number>
middle_name: string | null
bio: string | undefined
avatar_url?: string
}
type InsertableUser = Insertable<UserTable>
// {
// username: string // required
// email: string // required
// id?: number // optional (Generated)
// middle_name?: string | null // optional (nullable)
// bio?: string | undefined // optional (nullable)
// avatar_url?: string // optional (optional in table)
// }
Different Types for Insert
interface EventTable {
id: Generated<number>
name: string
// Accept string for insert, but return Date for select
event_date: ColumnType<Date, string, string>
// JSON column: accept string, return object
metadata: ColumnType<{ tags: string[] }, string, string>
// Read-only column
created_at: ColumnType<Date, never, never>
}
type InsertableEvent = Insertable<EventTable>
// {
// id?: number
// name: string
// event_date: string
// metadata: string
// // created_at excluded (InsertType is never)
// }
await db
.insertInto('event')
.values({
name: 'Conference',
event_date: '2024-06-15',
metadata: JSON.stringify({ tags: ['tech', 'ai'] })
})
.execute()
Common Patterns
Function Parameters
type InsertablePerson = Insertable<PersonTable>
async function createPerson(person: InsertablePerson) {
return await db
.insertInto('person')
.values(person)
.returningAll()
.executeTakeFirstOrThrow()
}
// Usage
const person = await createPerson({
first_name: 'John',
last_name: 'Doe',
created_at: new Date().toISOString()
})
Bulk Inserts
type InsertablePerson = Insertable<PersonTable>
const people: InsertablePerson[] = [
{ first_name: 'John', last_name: 'Doe', created_at: '2024-01-01' },
{ first_name: 'Jane', last_name: 'Smith', created_at: '2024-01-02' },
]
await db
.insertInto('person')
.values(people)
.execute()
Combining with Selectable
import { Selectable, Insertable } from 'kysely'
type Person = Selectable<PersonTable>
type NewPerson = Insertable<PersonTable>
async function createPerson(newPerson: NewPerson): Promise<Person> {
return await db
.insertInto('person')
.values(newPerson)
.returningAll()
.executeTakeFirstOrThrow()
}
Partial Insertable with Pick
// Only require certain fields
type PersonNameOnly = Pick<InsertablePerson, 'first_name' | 'last_name'>
function validatePersonName(name: PersonNameOnly) {
if (!name.first_name || !name.last_name) {
throw new Error('Name is required')
}
}
Source
View source on GitHub