• Start

Languages

/

JavaScript

/

Concepts

Value types

The SQON library provides custom classes for SurrealDB-specific data types, re-exported by the JavaScript SDK for convenience.

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.

ClassDescription
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.)

SurrealQL types map to JavaScript types as follows:

SurrealQL typeJavaScript typeExample
boolbooleantrue, false
int, floatnumber42, 3.14
stringstring"hello"
nullnullnull
noneundefinedundefined
arrayArray[1, 2, 3]
objectObject{`{ key: "value" }`}
setSetnew Set([1, 2, 3])
bytesUint8Arraynew Uint8Array([...])
recordRecordIdnew RecordId('users', 'john')
-Tablenew Table('users')
datetimeDateTimeDateTime.now()
durationDurationDuration.parse('1h30m')
decimalDecimalnew Decimal('19.99')
uuidUuidUuid.v7()
geometryGeometry*new GeometryPoint([1, 2])
rangeRangenew Range(1, 10)
fileFileRefrecord.avatar

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);

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();

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();

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');

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);

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);
}

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]),
]);

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');

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,
},
});

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`;
const users = new Table<User>('users');
const results: User[] = await db.select(users);

const userId = new RecordId<'users', string>('users', 'john');
await db.select(new RecordId('users', 'john'));

// Avoid string-based queries when possible
await db.query('SELECT * FROM users:john');
try {
const uuid = Uuid.parse(userInput);
} catch (error) {
console.error('Invalid UUID format');
}

Was this page helpful?