The method allows updating a document. It’s available on Collection
, Ref
, and Doc
.
The method returns Ref
instance:
const ref = await db . users . update (userId , { name: " Alexander " } );
Typesaurus accepts partial data. If the document doesn’t exist, it will throw an error.
Want to set if doesn’t exist?
As update
throws an error if the document doesn’t exist, if you want to update or set if the document doesn’t exist, you can use the upset
method that does just that.
It accepts a function as the argument that allows you to use the $
helper object:
await db . users . update (userId, ( $ ) => ({
updatedAt: $ . serverDate (),
Deep fields update
You can update individual fields, including nested ones, using $.field
helper:
await db . users . update (userId, ( $ ) => [
$ . field ( " name " ) . set ( " Sasha " ),
$ . field ( " address " , " city " ) . set ( " San Jose " ),
It allows you to update multiple disconnected fields at once.
When updating nested fields, make sure you use “safe paths” to prevent data inconsistency.
→ Read more about safe paths .
Builder mode
The update
also allows you to use the builder mode, where you accumulate the update operations and then call run
to execute them:
// Start building the update
const $ = db . users . update . build (userId);
$ . field ( " updatedAt " ) . set ($ . serverDate ());
// ...Do something in between, including async operations
$ . field ( " address " , " city " ) . set ( " San Jose " );
Just like the function argument, the builder has the same set of helpers:
Variable model
When updating a variable model, you can only update using the complete data or partial shared data:
const db = schema ( ( $ ) => ( {
accounts: $ . collection < [ GitHubAccount , MicrosoftAccount , GoogleAccount ] > () ,
interface GitHubAccount {
interface MicrosoftAccount {
interface GoogleAccount {
// OK! We're updating a shared field.
await db . accounts . update (accountId, {
// OK! We're updating with complete data.
await db . accounts . update (accountId, {
email: " example@example.com " ,
await db . accounts . update (accountId, {
// Email is only available for GoogleAccount
email: " example@example.com " ,
//=> Object literal may only specify known properties, and 'email' does not exist in type 'Arg<SharedShape3<GitHubAccount, MicrosoftAccount, GoogleAccount>, DocProps & { environment: RuntimeEnvironment; }>'.ts(2353)
You can also narrow the model before updating. Then, the partial update will be available:
const account = await db . accounts . get (accountId);
const googleAccount = account . narrow (
( data ) => data . type === " google " && data ,
await googleAccount ?. update ({
email: " example@example.com " ,
→ Read more about variable models .
$
helper
The argument function receives the $
helper object as the first argument that provides write helpers.
$
type is TypesaurusUpdate.Helpers
.
The function can return a falsy value to skip the update:
// Will not update the document as the name is undefined
await db . users . update (userId, ( $ ) => name && { name });
A skipped update call will return undefined
.
$.field
The helper allows to update individual fields, including nested ones:
await db . users . update (userId, ( $ ) => [
$ . field ( " name " ) . set ( " Sasha " ),
$ . field ( " address " , " city " ) . set ( " San Jose " ),
You can return an array of helpers to update multiple fields at once. You also can return a single field:
await db . users . update (userId, ( $ ) =>
$ . field ( " address " , " city " ) . set ( " San Jose " ),
If you return a falsy value, the update will be skipped:
( $ ) => city && $ . field ( " address " , " city " ) . set (city),
$.field(...).set
The set
function allows setting a value to a field. It always accepts the field type or corresponding system value produced by a help like $.serverDate()
:
await db . users . update (userId, ( $ ) => $ . field ( " name " ) . set ( " Sasha " ));
$.serverDate
To assign a server date to a field, use $.serverDate
:
await db . users . update (userId, ( $ ) => ({
// Set updatedAt to the server date
updatedAt: $ . serverDate (),
It will assign the date when Firestore saves the document.
→ Read more about server dates .
$.remove
To remove a field, use $.remove
:
await db . users . update (userId, ( $ ) => ({
Removing a field that is not optional will show you a type error.
$.increment
To increment a number field, use $.increment
:
await db . users . update (userId, ( $ ) => ({
// Increment the kudos field by 1
The method is only available for the number fields.
$.arrayUnion
To add an item to an array field, use $.arrayUnion
:
await db . users . update (userId, ( $ ) => ({
// Add "cool" tag to the tags array
tags: $ . arrayUnion ( " cool " ),
The method is only available for the array fields.
$.arrayRemove
To remove an item from an array field, use $.arrayRemove
:
await db . users . update (userId, ( $ ) => ({
// Remove the "cool" tag from the tags array
tags: $ . arrayRemove ( " cool " ),
The method is only available for the array fields.
Options
as
You can tell Typesaurus that it’s safe to set dates to server dates by passing the as
option ("server" | "client"
):
import { Typesaurus } from " typesaurus " ;
updatedAt : Typesaurus . ServerDate ;
// Can't assign Date to ServerDate
await db . users . update (userId, ( $ ) => ({
//=> The types of 'updatedAt' are incompatible between these types.
//=> Type 'Date' is missing the following properties from type 'ValueServerDate': type, kind
// OK! We're on the server
By default, Typesaurus uses the "client"
option.
The builder mode also accepts the as
option:
const $ = db . users . update . build (userId , { as: " server " } );
$ . field ( " updatedAt " ) . set ( new Date ());
→ Read more about server dates .