Specialized data types for Firestore including timestamps, geographic points, binary data, and field values with their type-safe operations.
Represents a point in time with nanosecond precision.
class Timestamp {
/** Create timestamp from seconds and nanoseconds */
constructor(seconds: number, nanoseconds: number);
/** Create timestamp for current time */
static now(): Timestamp;
/** Create timestamp from JavaScript Date */
static fromDate(date: Date): Timestamp;
/** Create timestamp from milliseconds since epoch */
static fromMillis(milliseconds: number): Timestamp;
/** Seconds since Unix epoch */
readonly seconds: number;
/** Nanoseconds within the second (0-999,999,999) */
readonly nanoseconds: number;
/** Convert to JavaScript Date */
toDate(): Date;
/** Convert to milliseconds since epoch */
toMillis(): number;
/** Check if this timestamp equals another */
isEqual(other: Timestamp): boolean;
/** String representation for JSON serialization */
valueOf(): string;
}Represents a geographic location with latitude and longitude.
class GeoPoint {
/** Create geographic point */
constructor(latitude: number, longitude: number);
/** Latitude in degrees (-90 to 90) */
readonly latitude: number;
/** Longitude in degrees (-180 to 180) */
readonly longitude: number;
/** Check if this point equals another */
isEqual(other: GeoPoint): boolean;
}Represents binary data stored in Firestore.
class Blob {
private constructor();
/** Create blob from base64 string */
static fromBase64String(base64: string): Blob;
/** Create blob from byte array */
static fromUint8Array(array: Uint8Array): Blob;
/** Convert to base64 string */
toBase64(): string;
/** Convert to byte array */
toUint8Array(): Uint8Array;
/** Check if this blob equals another */
isEqual(other: Blob): boolean;
}Sentinel values for special field operations.
class FieldValue {
private constructor();
/** Server timestamp placeholder */
static serverTimestamp(): FieldValue;
/** Delete field placeholder */
static delete(): FieldValue;
/** Add elements to array field */
static arrayUnion(...elements: any[]): FieldValue;
/** Remove elements from array field */
static arrayRemove(...elements: any[]): FieldValue;
/** Increment numeric field */
static increment(n: number): FieldValue;
/** Check if this field value equals another */
isEqual(other: FieldValue): boolean;
}import type { Timestamp } from "@firebase/firestore-types";
interface Event {
name: string;
createdAt: Timestamp;
scheduledFor: Timestamp;
}
function handleTimestamps() {
// Create timestamps
const now = Timestamp.now();
const fromDate = Timestamp.fromDate(new Date('2024-01-01'));
const fromMillis = Timestamp.fromMillis(Date.now());
const precise = new Timestamp(1640995200, 500000000); // 500ms precision
// Convert timestamps
console.log('As Date:', now.toDate());
console.log('As milliseconds:', now.toMillis());
console.log('Seconds:', now.seconds);
console.log('Nanoseconds:', now.nanoseconds);
// Compare timestamps
const earlier = Timestamp.fromDate(new Date('2023-01-01'));
const later = Timestamp.fromDate(new Date('2024-01-01'));
console.log('Are equal:', earlier.isEqual(later)); // false
return { now, fromDate, fromMillis, precise };
}
async function saveEvent(docRef: DocumentReference<Event>) {
const event: Event = {
name: "Team Meeting",
createdAt: Timestamp.now(),
scheduledFor: Timestamp.fromDate(new Date('2024-12-25'))
};
await docRef.set(event);
}import type { GeoPoint } from "@firebase/firestore-types";
interface Location {
name: string;
coordinates: GeoPoint;
accuracy: number;
}
function handleGeoPoints() {
// Create geographic points
const nyc = new GeoPoint(40.7128, -74.0060);
const sf = new GeoPoint(37.7749, -122.4194);
const london = new GeoPoint(51.5074, -0.1278);
// Access coordinates
console.log(`NYC: ${nyc.latitude}, ${nyc.longitude}`);
console.log(`SF: ${sf.latitude}, ${sf.longitude}`);
// Compare points
const nycCopy = new GeoPoint(40.7128, -74.0060);
console.log('NYC equals copy:', nyc.isEqual(nycCopy)); // true
console.log('NYC equals SF:', nyc.isEqual(sf)); // false
return { nyc, sf, london };
}
async function saveLocation(docRef: DocumentReference<Location>) {
const location: Location = {
name: "Central Park",
coordinates: new GeoPoint(40.7829, -73.9654),
accuracy: 10 // meters
};
await docRef.set(location);
}
// Query by geographic proximity (requires composite index)
function queryNearby(collection: CollectionReference<Location>) {
const center = new GeoPoint(40.7829, -73.9654);
const radiusInLat = 0.01; // Approximate degrees for desired radius
return collection
.where('coordinates', '>', new GeoPoint(center.latitude - radiusInLat, -180))
.where('coordinates', '<', new GeoPoint(center.latitude + radiusInLat, 180));
}import type { Blob } from "@firebase/firestore-types";
interface FileRecord {
name: string;
content: Blob;
mimeType: string;
size: number;
}
function handleBlobs() {
// Create from base64
const base64Data = "SGVsbG8gV29ybGQ="; // "Hello World"
const blobFromBase64 = Blob.fromBase64String(base64Data);
// Create from byte array
const bytes = new Uint8Array([72, 101, 108, 108, 111]); // "Hello"
const blobFromBytes = Blob.fromUint8Array(bytes);
// Convert blob data
console.log('As base64:', blobFromBytes.toBase64());
console.log('As bytes:', blobFromBytes.toUint8Array());
// Compare blobs
const sameBytesBlob = Blob.fromUint8Array(new Uint8Array([72, 101, 108, 108, 111]));
console.log('Blobs equal:', blobFromBytes.isEqual(sameBytesBlob)); // true
return { blobFromBase64, blobFromBytes };
}
async function uploadFile(docRef: DocumentReference<FileRecord>, fileData: ArrayBuffer) {
const bytes = new Uint8Array(fileData);
const blob = Blob.fromUint8Array(bytes);
const record: FileRecord = {
name: "document.pdf",
content: blob,
mimeType: "application/pdf",
size: bytes.length
};
await docRef.set(record);
}import type { FieldValue } from "@firebase/firestore-types";
interface UserProfile {
name: string;
lastLogin: FieldValue | Timestamp;
loginCount: number;
tags: string[];
preferences?: { [key: string]: any };
}
async function useFieldValues(docRef: DocumentReference<UserProfile>) {
// Set server timestamp
await docRef.update({
lastLogin: FieldValue.serverTimestamp()
});
// Increment counter
await docRef.update({
loginCount: FieldValue.increment(1)
});
// Array operations
await docRef.update({
tags: FieldValue.arrayUnion("premium", "verified")
});
await docRef.update({
tags: FieldValue.arrayRemove("trial")
});
// Delete field
await docRef.update({
preferences: FieldValue.delete()
});
}
// Atomic batch operations with field values
async function batchFieldOperations(batch: WriteBatch, docRef: DocumentReference<UserProfile>) {
batch.update(docRef, {
lastLogin: FieldValue.serverTimestamp(),
loginCount: FieldValue.increment(1),
tags: FieldValue.arrayUnion("active")
});
await batch.commit();
}interface ComplexDocument {
id: string;
createdAt: Timestamp;
location: GeoPoint;
fileData: Blob;
metadata: {
version: number;
tags: string[];
lastModified: Timestamp;
};
}
async function handleComplexDocument(docRef: DocumentReference<ComplexDocument>) {
const complexData: ComplexDocument = {
id: "doc-123",
createdAt: Timestamp.now(),
location: new GeoPoint(37.7749, -122.4194),
fileData: Blob.fromBase64String("VGVzdCBkYXRh"), // "Test data"
metadata: {
version: 1,
tags: ["important", "draft"],
lastModified: Timestamp.now()
}
};
// Save document
await docRef.set(complexData);
// Update with field values
await docRef.update({
"metadata.version": FieldValue.increment(1),
"metadata.tags": FieldValue.arrayUnion("reviewed"),
"metadata.lastModified": FieldValue.serverTimestamp()
});
// Read and process
const snapshot = await docRef.get();
if (snapshot.exists) {
const data = snapshot.data();
console.log('Created:', data?.createdAt.toDate());
console.log('Location:', `${data?.location.latitude}, ${data?.location.longitude}`);
console.log('File size:', data?.fileData.toUint8Array().length, 'bytes');
console.log('Version:', data?.metadata.version);
}
}