@@ -53,149 +53,159 @@ import { SnapshotListenOptions } from './reference_impl';
53
53
* Simple Example
54
54
*
55
55
* ```typescript
56
- * const numberConverter = {
57
- * toFirestore(value: WithFieldValue<number>) {
58
- * return { value };
59
- * },
60
- * fromFirestore(snapshot: QueryDocumentSnapshot, options: SnapshotOptions) {
61
- * return snapshot.data(options).value as number;
62
- * }
56
+ * const numberConverter: FirestoreDataConverter<number, {value: number}> = {
57
+ * toFirestore(value: WithFieldValue<number>) {
58
+ * return { value };
59
+ * },
60
+ * fromFirestore(snapshot: QueryDocumentSnapshot, options: SnapshotOptions) {
61
+ * return snapshot.data(options).value as number;
62
+ * }
63
63
* };
64
64
*
65
65
* async function simpleDemo(db: Firestore): Promise<void> {
66
- * const documentRef = doc(db, 'values/value123').withConverter(numberConverter);
66
+ * const documentRef = doc(db, 'values/value123').withConverter(numberConverter);
67
67
*
68
- * await setDoc(documentRef, 42);
69
- * const snapshot1 = await getDoc(documentRef);
70
- * assertEqual(snapshot1.data(), 42);
68
+ * // converters are used with `setDoc`, `addDoc`, and `getDoc`
69
+ * await setDoc(documentRef, 42);
70
+ * const snapshot1 = await getDoc(documentRef);
71
+ * assertEqual(snapshot1.data(), 42);
71
72
*
72
- * await updateDoc(documentRef, { value: 999 });
73
- * const snapshot2 = await getDoc(documentRef);
74
- * assertEqual(snapshot2.data(), 999);
73
+ * // converters are not used when writing data with `updateDoc`
74
+ * await updateDoc(documentRef, { value: 999 });
75
+ * const snapshot2 = await getDoc(documentRef);
76
+ * assertEqual(snapshot2.data(), 999);
75
77
* }
76
78
* ```
77
79
*
78
80
* Advanced Example
79
81
*
80
82
* ```typescript
83
+ * // The Post class is a model that is used by our application.
84
+ * // This class may have properties and methods that are specific
85
+ * // to our application execution, which do not need to be persisted
86
+ * // to Firestore.
81
87
* class Post {
82
- * constructor(
83
- * readonly title: string,
84
- * readonly author: string,
85
- * readonly lastUpdatedMillis: number
86
- * ) {}
87
- *
88
- * toString(): string {
89
- * return `${this.title} by ${this.author}`;
90
- * }
88
+ * constructor(
89
+ * readonly title: string,
90
+ * readonly author: string,
91
+ * readonly lastUpdatedMillis: number
92
+ * ) {}
93
+ * toString(): string {
94
+ * return `${this.title} by ${this.author}`;
95
+ * }
91
96
* }
92
97
*
98
+ * // The PostDbModel represents how we want our posts to be stored
99
+ * // in Firestore. This DbModel has different properties (`ttl`,
100
+ * // `aut`, and `lut`) from the Post class we use in our application.
93
101
* interface PostDbModel {
94
- * ttl: string;
95
- * aut: { firstName: string; lastName: string };
96
- * lut: Timestamp;
102
+ * ttl: string;
103
+ * aut: { firstName: string; lastName: string };
104
+ * lut: Timestamp;
97
105
* }
98
106
*
99
- * const postConverter = {
100
- * toFirestore(post: WithFieldValue<Post>) {
101
- * return {
102
- * ttl: post.title,
103
- * aut: this._autFromAuthor(post.author),
104
- * lut: this._lutFromLastUpdatedMillis(post.lastUpdatedMillis)
105
- * };
106
- * },
107
+ * // The `PostConverter` implements `FirestoreDataConverter<AppModelType, DbModelType>`
108
+ * // and specifies how the Firestore SDK can convert `Post` objects to `PostDbModel`
109
+ * // objects and vice versa.
110
+ * class PostConverter implements FirestoreDataConverter<Post, PostDbModel> {
111
+ * toFirestore(post: WithFieldValue<Post>) {
112
+ * return {
113
+ * ttl: post.title,
114
+ * aut: this._autFromAuthor(post.author),
115
+ * lut: this._lutFromLastUpdatedMillis(post.lastUpdatedMillis)
116
+ * };
117
+ * }
107
118
*
108
- * fromFirestore(snapshot: QueryDocumentSnapshot, options: SnapshotOptions) {
109
- * const data = snapshot.data(options) as PostDbModel;
110
- * const author = `${data.aut.firstName} ${data.aut.lastName}`;
111
- * return new Post(data.ttl, author, data.lut.toMillis());
112
- * },
119
+ * fromFirestore(snapshot: QueryDocumentSnapshot, options: SnapshotOptions) {
120
+ * const data = snapshot.data(options) as PostDbModel;
121
+ * const author = `${data.aut.firstName} ${data.aut.lastName}`;
122
+ * return new Post(data.ttl, author, data.lut.toMillis());
123
+ * }
113
124
*
114
- * _autFromAuthor(
115
- * author: string | FieldValue
116
- * ): { firstName: string; lastName: string } | FieldValue {
117
- * if (typeof author !== 'string') {
118
- * // `author` is a FieldValue, so just return it.
119
- * return author;
125
+ * _autFromAuthor(
126
+ * author: string | FieldValue
127
+ * ): { firstName: string; lastName: string } | FieldValue {
128
+ * if (typeof author !== 'string') {
129
+ * // `author` is a FieldValue, so just return it.
130
+ * return author;
131
+ * }
132
+ * const [firstName, lastName] = author.split(' ');
133
+ * return {firstName, lastName};
120
134
* }
121
- * const [firstName, lastName] = author.split(' ');
122
- * return { firstName, lastName };
123
- * },
124
135
*
125
- * _lutFromLastUpdatedMillis(
126
- * lastUpdatedMillis: number | FieldValue
127
- * ): Timestamp | FieldValue {
128
- * if (typeof lastUpdatedMillis !== 'number') {
129
- * // `lastUpdatedMillis` must be a FieldValue, so just return it.
130
- * return lastUpdatedMillis;
136
+ * _lutFromLastUpdatedMillis(
137
+ * lastUpdatedMillis: number | FieldValue
138
+ * ): Timestamp | FieldValue {
139
+ * if (typeof lastUpdatedMillis !== 'number') {
140
+ * // `lastUpdatedMillis` must be a FieldValue, so just return it.
141
+ * return lastUpdatedMillis;
142
+ * }
143
+ * return Timestamp.fromMillis(lastUpdatedMillis);
131
144
* }
132
- * return Timestamp.fromMillis(lastUpdatedMillis);
133
- * }
134
- * };
145
+ * }
135
146
*
136
147
* async function advancedDemo(db: Firestore): Promise<void> {
137
- * // Create a `DocumentReference` with a `FirestoreDataConverter`.
138
- * const documentRef = doc(db, 'posts/post123').withConverter(postConverter);
139
- *
140
- * // The `data` argument specified to `setDoc()` is type checked by the
141
- * // TypeScript compiler to be compatible with `Post`. Since the `data`
142
- * // argument is typed as `WithFieldValue<Post>` rather than just `Post`,
143
- * // this allows properties of the `data` argument to also be special
144
- * // Firestore values that perform server-side mutations, such as
145
- * // `arrayRemove()`, `deleteField()`, and `serverTimestamp()`.
146
- * await setDoc(documentRef, {
147
- * title: 'My Life',
148
- * author: 'Foo Bar',
149
- * lastUpdatedMillis: serverTimestamp()
150
- * });
148
+ * // Create a `DocumentReference` with a `FirestoreDataConverter`.
149
+ * const documentRef = doc(db, 'posts/post123').withConverter(new PostConverter());
151
150
*
152
- * // The TypeScript compiler will fail to compile if the `data` argument to
153
- * // `setDoc()` is _not_ be compatible with `WithFieldValue<Post>`. This
154
- * // type checking prevents the caller from specifying objects with incorrect
155
- * // properties or property values.
156
- * // @ts -expect-error "Argument of type { ttl: string; } is not assignable
157
- * // to parameter of type WithFieldValue<Post>"
158
- * await setDoc(documentRef, { ttl: 'The Title' });
151
+ * // The `data` argument specified to `setDoc()` is type checked by the
152
+ * // TypeScript compiler to be compatible with `Post`. Since the `data`
153
+ * // argument is typed as `WithFieldValue<Post>` rather than just `Post`,
154
+ * // this allows properties of the `data` argument to also be special
155
+ * // Firestore values that perform server-side mutations, such as
156
+ * // `arrayRemove()`, `deleteField()`, and `serverTimestamp()`.
157
+ * await setDoc(documentRef, {
158
+ * title: 'My Life',
159
+ * author: 'Foo Bar',
160
+ * lastUpdatedMillis: serverTimestamp()
161
+ * });
159
162
*
160
- * // When retrieving a document with `getDoc()` the `DocumentSnapshot`
161
- * // object's `data()` method returns a `Post`, rather than a generic object,
162
- * // which is returned if the `DocumentReference` did _not_ have a
163
- * // `FirestoreDataConverter` attached to it.
164
- * const snapshot1: DocumentSnapshot<Post> = await getDoc(documentRef);
165
- * const post1: Post = snapshot1.data()!;
166
- * if (post1) {
167
- * assertEqual(post1.title, 'My Life');
168
- * assertEqual(post1.author, 'Foo Bar');
169
- * }
163
+ * // The TypeScript compiler will fail to compile if the `data` argument to
164
+ * // `setDoc()` is _not_ be compatible with `WithFieldValue<Post>`. This
165
+ * // type checking prevents the caller from specifying objects with incorrect
166
+ * // properties or property values.
167
+ * // @ts -expect-error "Argument of type { ttl: string; } is not assignable
168
+ * // to parameter of type WithFieldValue<Post>"
169
+ * await setDoc(documentRef, { ttl: 'The Title' });
170
170
*
171
- * // The `data` argument specified to `updateDoc()` is type checked by the
172
- * // TypeScript compiler to be compatible with `PostDbModel`. Note that
173
- * // unlike `setDoc()`, whose `data` argument must be compatible with `Post`,
174
- * // the `data` argument to `updateDoc()` must be compatible with
175
- * // `PostDbModel`. Similar to `setDoc()`, since the `data` argument is typed
176
- * // as `WithFieldValue<PostDbModel>` rather than just `PostDbModel`, this
177
- * // allows properties of the `data` argument to also be those special
178
- * // Firestore values, like as `arrayRemove()`, `deleteField()`, and
179
- * // `serverTimestamp()`.
180
- * await updateDoc(documentRef, {
181
- * 'aut.firstName': 'NewFirstName',
182
- * lut: serverTimestamp()
183
- * });
171
+ * // When retrieving a document with `getDoc()` the `DocumentSnapshot`
172
+ * // object's `data()` method returns a `Post`, rather than a generic object,
173
+ * // which would have been returned if the `DocumentReference` did _not_ have a
174
+ * // `FirestoreDataConverter` attached to it.
175
+ * const snapshot1: DocumentSnapshot<Post> = await getDoc(documentRef);
176
+ * const post1: Post = snapshot1.data()!;
177
+ * if (post1) {
178
+ * assertEqual(post1.title, 'My Life');
179
+ * assertEqual(post1.author, 'Foo Bar');
180
+ * }
184
181
*
185
- * // The TypeScript compiler will fail to compile if the `data` argument to
186
- * // `updateDoc()` is _not_ be compatible with `WithFieldValue<PostDbModel>`.
187
- * // This type checking prevents the caller from specifying objects with
188
- * // incorrect properties or property values.
189
- * // @ts -expect-error "Argument of type { title: string; } is not assignable
190
- * // to parameter of type WithFieldValue<PostDbModel>"
191
- * await updateDoc(documentRef, { title: 'New Title' });
182
+ * // The `data` argument specified to `updateDoc()` is type checked by the
183
+ * // TypeScript compiler to be compatible with `PostDbModel`. Note that
184
+ * // unlike `setDoc()`, whose `data` argument must be compatible with `Post`,
185
+ * // the `data` argument to `updateDoc()` must be compatible with
186
+ * // `PostDbModel`. Similar to `setDoc()`, since the `data` argument is typed
187
+ * // as `WithFieldValue<PostDbModel>` rather than just `PostDbModel`, this
188
+ * // allows properties of the `data` argument to also be those special
189
+ * // Firestore values, like as `arrayRemove()`, `deleteField()`, and
190
+ * // `serverTimestamp()`.
191
+ * await updateDoc(documentRef, {
192
+ * 'aut.firstName': 'NewFirstName',
193
+ * lut: serverTimestamp()
194
+ * });
192
195
*
193
- * const snapshot2: DocumentSnapshot<Post> = await getDoc(documentRef);
194
- * const post2: Post = snapshot2.data()!;
195
- * if (post2) {
196
- * assertEqual(post2.title, 'My Life');
197
- * assertEqual(post2.author, 'NewFirstName Bar');
198
- * }
196
+ * // The TypeScript compiler will fail to compile if the `data` argument to
197
+ * // `updateDoc()` is _not_ be compatible with `WithFieldValue<PostDbModel>`.
198
+ * // This type checking prevents the caller from specifying objects with
199
+ * // incorrect properties or property values.
200
+ * // @ts -expect-error "Argument of type { title: string; } is not assignable
201
+ * // to parameter of type WithFieldValue<PostDbModel>"
202
+ * await updateDoc(documentRef, { title: 'New Title' });
203
+ * const snapshot2: DocumentSnapshot<Post> = await getDoc(documentRef);
204
+ * const post2: Post = snapshot2.data()!;
205
+ * if (post2) {
206
+ * assertEqual(post2.title, 'My Life');
207
+ * assertEqual(post2.author, 'NewFirstName Bar');
208
+ * }
199
209
* }
200
210
* ```
201
211
*/
0 commit comments