Custom data types
In addition to built-in data types, LDkit supports custom two-way conversion between RDF based data types and JavaScript / TypeScript native types. Both data and TypeScript types are adequately converted.
This is useful when working with complex data formats, such as geometrical points, dates, monetary values, or domain-specific representations that require special parsing and serialization.
In order to support custom types, you must provide a proper TypeScript type definition and register conversion functions to translate between RDF literal values and JavaScript primitives.
Use Case Example: Handling Geospatial Coordinates (WKT)
In this guide, we will demonstrate how to handle geospatial coordinates using
the
WKT (Well-Known Text)
format by mapping it to a custom Point
class in TypeScript.
Point
class implementation
Step 1: Create Below is a simple class representing a geographical point with longitude and
latitude properties. Function fromWKT
parses a WKT string and converts it into
a Point
object. Function toWKT
serializes a Point
object back into a WKT
string.
class Point {
constructor(public long: number, public lat: number) {}
static fromWKT(wkt: string): Point {
const match = wkt.match(/POINT\(([^ ]+) ([^ ]+)\)/);
if (!match) {
throw new Error("Invalid WKT format");
}
const [, long, lat] = match;
return new Point(parseFloat(long), parseFloat(lat));
}
static toWKT(point: Point): string {
return `<http://www.opengis.net/def/crs/EPSG/0/4326> POINT(${point.long} ${point.lat})`;
}
}
Step 2: Create a custom namespace and schema
import { createNamespace, type Schema } from "ldkit";
const geo = createNamespace(
{
iri: "http://www.opengis.net/ont/geosparql#",
prefix: "geo:",
terms: [
"Geometry",
"asWKT",
"wktLiteral",
],
} as const,
);
const GeometrySchema = {
"@type": geo.Geometry,
point: {
"@id": geo.asWKT,
"@type": geo.wktLiteral, // This is the custom type definition in schema
},
} satisfies Schema;
Step 3: Register the new custom type with LDkit
There are two parts to registering a new custom type. First, the
CustomDataTypes
interface must be augmented to include a mapping from the new
type to the desired TypeScript type. Second, conversion functions must be
provided using the registerDataHandler
function.
import { registerDataHandler } from "ldkit";
// TypeScript compile time type conversion
declare module "ldkit" {
interface CustomDataTypes {
[geo.wktLiteral]: Point;
}
}
// Actual runtime data conversion
registerDataHandler(
geo.wktLiteral,
(literalValue: string) => Point.fromWKT(literalValue),
(nativeValue: Point) => Point.toWKT(nativeValue),
);
Step 4: Query and update data
Having registered the custom data type, you can use it directly in LDkit for both reading and writing RDF data.
const Entities = createLens(GeometrySchema);
await Entities.insert({
$id: "http://example.org/geometry/testGeometry",
point: new Point(49.76700621977145, -7.556765719356096),
});
const record = await Entities.findByIri(
"http://example.org/geometry/testGeometry",
);
console.log(record.point); // Point { long: 49.76700621977145, lat: -7.556765719356096 }