Skip to main content
When working with data types in Kysely, it’s crucial to understand the distinction between TypeScript types and runtime JavaScript types.

TypeScript types vs runtime types

TypeScript types

Compile-time only. You define these for your tables and columns.

Runtime types

Actual JavaScript values returned by the database driver.

TypeScript types

In Kysely, you only define TypeScript types for your tables and columns. Since TypeScript is entirely a compile-time concept, TypeScript types cannot affect runtime JavaScript types.
If you define your column to be a string in TypeScript but the database returns a number, the runtime type doesn’t magically change to string. You’ll see a string in the TypeScript code, but observe a number when you run the program.
It’s up to you to select correct TypeScript types for your columns based on what the driver returns.

Runtime JavaScript types

The database driver (such as pg or mysql2) decides the runtime JavaScript types that queries return. Kysely never touches the runtime types the driver returns.
Kysely doesn’t modify data returned by the driver in any way — it simply executes the query and returns whatever the driver returns. An exception is when you use a plugin like CamelCasePlugin, which changes column names.
You need to:
  1. Read the underlying driver’s documentation
  2. Figure out what the driver returns
  3. Align your TypeScript types to match

Configuring runtime JavaScript types

Most drivers provide ways to change the returned types. Here’s how to configure common scenarios:

PostgreSQL

When using the pg driver, use the pg-types package to configure types.

Example: Return bigint as number

By default, pg returns bigint and numeric types as strings. Here’s how to configure it to return numbers:
import { Kysely, PostgresDialect } from 'kysely'
import * as pg from 'pg'

const int8TypeId = 20

// Map int8 to number
pg.types.setTypeParser(int8TypeId, (val) => {
  return parseInt(val, 10)
})

export const db = new Kysely<Database>({
  dialect: new PostgresDialect({
    pool: new pg.Pool(config),
  }),
})
See the pg-types documentation to figure out the correct type ID for your data type.

MySQL

When using the mysql2 driver, use the typeCast pool property.

Example: Map tinyint(1) to boolean

import { Kysely, MysqlDialect } from 'kysely'
import { createPool } from 'mysql2'

export const db = new Kysely<Database>({
  dialect: new MysqlDialect({
    pool: createPool({
      ...config,
      // Map tinyint(1) to boolean
      typeCast(field, next) {
        if (field.type === 'TINY' && field.length === 1) {
          return field.string() === '1'
        } else {
          return next()
        }
      },
    }),
  }),
})

Type generators

Third-party type generators can automatically generate TypeScript types from your database schema:

kysely-codegen

Generate types from your database schema

kanel-kysely

Another popular type generation tool
Find out more at the Generating types documentation.
If these tools generate a type that doesn’t match the runtime type you observe, refer to their documentation or open an issue in their GitHub repository. Kysely has no control over these libraries.

Common type mismatches

Here are some common scenarios where TypeScript types and runtime types might differ:
Database TypeDefault Runtime TypeCommon TypeScript TypeNotes
PostgreSQL bigintstringnumberConfigure with pg-types
PostgreSQL numericstringnumberConfigure with pg-types
MySQL tinyint(1)numberbooleanConfigure with typeCast
PostgreSQL jsonobjectTAutomatically parsed
SQLite jsonstringTUse ParseJSONResultsPlugin

Best practices

1

Test your types

Always verify that runtime types match your TypeScript definitions by logging actual query results.
2

Configure driver early

Set up type parsing in your database configuration file before creating queries.
3

Document custom types

Comment your database type configuration so other developers understand the mappings.
4

Use type generators

Consider using type generators to keep TypeScript types in sync with your database schema.

Build docs developers (and LLMs) love