SurrealDB has types that JavaScript does not: record IDs, nanosecond datetimes, arbitrary-precision decimals, and others. They live in @surrealdb/sqon, which also ships codecs and a few core utilities. The surrealdb package re-exports all of it, so either import path works:
// With the driver (usual choice)
import { RecordId, Table, DateTime } from 'surrealdb';
// SQON only (no database client)
import { RecordId, Table, DateTime } from '@surrealdb/sqon';The classes validate input, keep database precision, and plug into query methods and codecs.
API references
Class | Description |
|---|---|
RecordId | Type-safe record identifiers with table and ID components |
Table | Type-safe table references for query methods |
DateTime | Datetime values with nanosecond precision |
Duration | Time duration values with multiple unit support |
Decimal | Arbitrary precision decimal numbers |
Uuid | Universally unique identifiers (v4 and v7) |
Range | Bounded or unbounded range values |
FileRef | References to files stored in SurrealDB |
Geometry* | GeoJSON geometry types (Point, Line, Polygon, etc.) |
Type mapping
SurrealQL types map to JavaScript types as follows:
SurrealQL type | JavaScript type | Example |
|---|---|---|
bool | boolean | true, false |
int, float | number | 42, 3.14 |
string | string | "hello" |
null | null | null |
none | undefined | undefined |
array | Array | [1, 2, 3] |
object | Object | {`{ key: "value" }`} |
set | Set | new Set([1, 2, 3]) |
bytes | Uint8Array | new Uint8Array([...]) |
record | RecordId | new RecordId('users', 'john') |
Table | new Table('users') | |
datetime | DateTime | DateTime.now() |
duration | Duration | Duration.parse('1h30m') |
decimal | Decimal | new Decimal('19.99') |
uuid | Uuid | Uuid.v7() |
geometry | Geometry* | new GeometryPoint([1, 2]) |
range | Range | new Range(1, 10) |
file | FileRef | record.avatar |
RecordId and Table
A RecordId is a table name plus an ID. A Table is a table reference on its own. From v2 onward, query methods expect a Table instance for table names, not a bare string, so table names are not confused with record IDs.
import { RecordId, Table } from 'surrealdb';
const userId = new RecordId('users', 'john');
const user = await db.select(userId);
const usersTable = new Table('users');
const allUsers = await db.select(usersTable);
const parsed = RecordId.parse('users:john');The ID component of a RecordId can be a string, number, bigint, Uuid, array, or object. The Table class also supports a type parameter for type-safe query results.
const users = new Table<User>('users');
const results: User[] = await db.select(users);DateTime and Duration
A DateTime is a timestamp with nanosecond precision. JavaScript's Date stops at milliseconds, so DateTime keeps what SurrealDB actually stored. A Duration follows SurrealQL duration syntax.
import { DateTime, Duration } from 'surrealdb';
const now = DateTime.now();
const parsed = DateTime.parse('2024-01-15T12:00:00.123456789Z');
const jsDate = now.toDate();
const iso = now.toString();
const duration = Duration.parse('1h30m45s');
const ms = duration.toMilliseconds();
const seconds = duration.toSeconds();Decimal
A Decimal holds a decimal without floating-point rounding. Construct it from a string when precision matters.
import { Decimal } from 'surrealdb';
const price = new Decimal('19.99');
const display = price.toString();
const number = price.toNumber(); Converting a Decimal to a number with .toNumber() may lose precision. Use .toString() when precision matters.
Uuid
A Uuid represents a universally unique identifier. The class supports generating both v4 (random) and v7 (time-ordered) UUIDs.
import { Uuid } from 'surrealdb';
const random = Uuid.v4();
const timeOrdered = Uuid.v7();
const parsed = Uuid.parse('550e8400-e29b-41d4-a716-446655440000');Range
A Range is a bounded or open-ended span of values. In SurrealQL you use ranges to slice record IDs or filter numbers and times. RecordIdRange is the variant for a table ID range.
import { Range, RecordIdRange } from 'surrealdb';
const numericRange = new Range(1, 10);
const idRange = new RecordIdRange('users', { begin: 'a', end: 'f' });
const slice = await db.select(idRange);FileRef
A FileRef points at a file stored in SurrealDB. You see one when working with file uploads; it carries bucket and key metadata.
const [record] = await db.query('SELECT avatar FROM user:john');
if (record.avatar instanceof FileRef) {
console.log(record.avatar.bucket);
console.log(record.avatar.key);
}Geometry types
The SDK provides classes for all GeoJSON geometry types: GeometryPoint, GeometryLine, GeometryPolygon, GeometryMultiPoint, GeometryMultiLine, GeometryMultiPolygon, and GeometryCollection.
import { GeometryPoint, GeometryLine, GeometryPolygon } from 'surrealdb';
const point = new GeometryPoint([longitude, latitude]);
const line = new GeometryLine([
new GeometryPoint([1, 2]),
new GeometryPoint([3, 4]),
]);Parsing from strings
Most classes accept the same string forms as SurrealQL. Invalid input throws.
const recordId = RecordId.parse('users:john');
const datetime = DateTime.parse('2024-01-15T12:00:00Z');
const duration = Duration.parse('1h30m45s');
const uuid = Uuid.parse('550e8400-e29b-41d4-a716-446655440000');Using native dates
By default, datetimes come back as DateTime. Set useNativeDates in codec options if you would rather work with Date and can accept millisecond precision.
const db = new Surreal({
codecOptions: {
useNativeDates: true,
},
});String prefixes
The surrealdb package includes tagged templates that mirror SurrealQL's s, d, r, and u prefixes. They are not part of @surrealdb/sqon.
import { s, d, r, u } from 'surrealdb';
const string = s`I am a string`;
const date = d`2024-05-06T17:44:57.085Z`;
const record = r`person:tobie`;
const uuid = u`92b84bde-39c8-4b4b-92f7-626096d6c4d9`;Best practices
Use type parameters for type-safe queries
const users = new Table<User>('users');
const results: User[] = await db.select(users);
const userId = new RecordId<'users', string>('users', 'john');Prefer value classes over raw strings
await db.select(new RecordId('users', 'john'));
// Avoid string-based queries when possible
await db.query('SELECT * FROM users:john');Validate parsed input
try {
const uuid = Uuid.parse(userInput);
} catch (error) {
console.error('Invalid UUID format');
}Learn more
Data types API reference for the full list of value class documentation
Codecs for serialising and deserialising value types
SurrealQL data model for the database-level type system
Utilities for comparing and converting values