feat(firestore): add isType expression (#9484)

This commit is contained in:
Daniel La Rocque
2026-02-23 14:36:00 -05:00
committed by GitHub
parent 9469aec4de
commit 7e2be93c09
12 changed files with 660 additions and 53 deletions
+6
View File
@@ -0,0 +1,6 @@
---
'firebase': minor
'@firebase/firestore': minor
---
feat(firestore): Support added for the `isType` Pipeline expression.
@@ -502,6 +502,8 @@ export abstract class Expression {
/* Excluded from this release type: _readUserData */
isError(): BooleanExpression;
/* Excluded from this release type: _readUserData */
isType(type: Type): BooleanExpression;
/* Excluded from this release type: _readUserData */
join(delimiterExpression: Expression): Expression;
/* Excluded from this release type: _readUserData */
join(delimiter: string): Expression;
@@ -771,6 +773,12 @@ export function isAbsent(field: string): BooleanExpression;
// @beta
export function isError(value: Expression): BooleanExpression;
// @beta
export function isType(fieldName: string, type: Type): BooleanExpression;
// @beta
export function isType(expression: Expression, type: Type): BooleanExpression;
// @beta
export function join(arrayFieldName: string, delimiter: string): Expression;
@@ -1376,6 +1384,9 @@ export function trunc(fieldName: string, decimalPlaces: number | Expression): Fu
// @beta
export function trunc(expression: Expression, decimalPlaces: number | Expression): FunctionExpression;
// @beta
export type Type = 'null' | 'array' | 'boolean' | 'bytes' | 'timestamp' | 'geo_point' | 'number' | 'int32' | 'int64' | 'float64' | 'decimal128' | 'map' | 'reference' | 'string' | 'vector' | 'max_key' | 'min_key' | 'object_id' | 'regex' | 'request_timestamp';
// @beta
export function type(fieldName: string): FunctionExpression;
@@ -505,6 +505,8 @@ export abstract class Expression {
/* Excluded from this release type: _readUserData */
isError(): BooleanExpression;
/* Excluded from this release type: _readUserData */
isType(type: Type): BooleanExpression;
/* Excluded from this release type: _readUserData */
join(delimiterExpression: Expression): Expression;
/* Excluded from this release type: _readUserData */
join(delimiter: string): Expression;
@@ -774,6 +776,12 @@ export function isAbsent(field: string): BooleanExpression;
// @beta
export function isError(value: Expression): BooleanExpression;
// @beta
export function isType(fieldName: string, type: Type): BooleanExpression;
// @beta
export function isType(expression: Expression, type: Type): BooleanExpression;
// @beta
export function join(arrayFieldName: string, delimiter: string): Expression;
@@ -1413,6 +1421,9 @@ export function trunc(fieldName: string, decimalPlaces: number | Expression): Fu
// @beta
export function trunc(expression: Expression, decimalPlaces: number | Expression): FunctionExpression;
// @beta
export type Type = 'null' | 'array' | 'boolean' | 'bytes' | 'timestamp' | 'geo_point' | 'number' | 'int32' | 'int64' | 'float64' | 'decimal128' | 'map' | 'reference' | 'string' | 'vector' | 'max_key' | 'min_key' | 'object_id' | 'regex' | 'request_timestamp';
// @beta
export function type(fieldName: string): FunctionExpression;
@@ -101,6 +101,7 @@ field("optional_field").ifAbsent(field('default_field'))
| [ifError(catchValue)](./firestore_lite_pipelines.expression.md#expressioniferror) | | <b><i>(Public Preview)</i></b> Creates an expression that returns the <code>catch</code> argument if there is an error, else return the result of this expression. |
| [isAbsent()](./firestore_lite_pipelines.expression.md#expressionisabsent) | | <b><i>(Public Preview)</i></b> Creates an expression that returns <code>true</code> if the result of this expression is absent. Otherwise, returns <code>false</code> even if the value is <code>null</code>. |
| [isError()](./firestore_lite_pipelines.expression.md#expressioniserror) | | <b><i>(Public Preview)</i></b> Creates an expression that checks if a given expression produces an error. |
| [isType(type)](./firestore_lite_pipelines.expression.md#expressionistype) | | <b><i>(Public Preview)</i></b> Creates an expression that checks if the result of this expression is of the given type. |
| [join(delimiterExpression)](./firestore_lite_pipelines.expression.md#expressionjoin) | | <b><i>(Public Preview)</i></b> Creates an expression that joins the elements of an array into a string. |
| [join(delimiter)](./firestore_lite_pipelines.expression.md#expressionjoin) | | <b><i>(Public Preview)</i></b> Creates an expression that joins the elements of an array field into a string. |
| [last()](./firestore_lite_pipelines.expression.md#expressionlast) | | <b><i>(Public Preview)</i></b> Creates an aggregation that finds the last value of an expression across multiple stage inputs. |
@@ -1977,6 +1978,42 @@ field("title").arrayContains(1).isError();
```
## Expression.isType()
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
>
Creates an expression that checks if the result of this expression is of the given type.
Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data.
<b>Signature:</b>
```typescript
isType(type: Type): BooleanExpression;
```
#### Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| type | [Type](./firestore_lite_pipelines.md#type) | The type to check for. |
<b>Returns:</b>
[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class)
A new `BooleanExpression` that evaluates to true if the expression's result is of the given type, false otherwise.
### Example
```typescript
// Check if the 'price' field is specifically an integer (not just 'number')
field('price').isType('int64');
```
## Expression.join()
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
@@ -4463,6 +4500,8 @@ field("rating").trunc(constant(2));
Creates an expression that returns the data type of this expression's result, as a string.
This is evaluated on the backend. This means: 1. Generic typed elements (like `array<string>`<!-- -->) evaluate strictly to the primitive `'array'`<!-- -->. 2. Any custom `FirestoreDataConverter` mappings are ignored. 3. For numeric values, the backend does not yield the JavaScript `"number"` type; it evaluates precisely as `"int64"` or `"float64"`<!-- -->. 4. For date or timestamp objects, the backend evaluates to `"timestamp"`<!-- -->.
<b>Signature:</b>
```typescript
+94
View File
@@ -87,6 +87,7 @@ https://github.com/firebase/firebase-js-sdk
| [first(expression)](./firestore_lite_pipelines.md#first_1138a27) | <b><i>(Public Preview)</i></b> Creates an aggregation that finds the first value of an expression across multiple stage inputs. |
| [greaterThan(expression, value)](./firestore_lite_pipelines.md#greaterthan_01df3cf) | <b><i>(Public Preview)</i></b> Creates an expression that checks if an expression is greater than a constant value. |
| [greaterThanOrEqual(expression, value)](./firestore_lite_pipelines.md#greaterthanorequal_01df3cf) | <b><i>(Public Preview)</i></b> Creates an expression that checks if an expression is greater than or equal to a constant value. |
| [isType(expression, type)](./firestore_lite_pipelines.md#istype_27398ce) | <b><i>(Public Preview)</i></b> Creates an expression that checks if the result of an expression is of the given type. |
| [last(expression)](./firestore_lite_pipelines.md#last_1138a27) | <b><i>(Public Preview)</i></b> Creates an aggregation that finds the last value of an expression across multiple stage inputs. |
| [length\_2(expression)](./firestore_lite_pipelines.md#length_2_1138a27) | <b><i>(Public Preview)</i></b> Creates an expression that calculates the length of a string, array, map, vector, or bytes. |
| [lessThan(expression, value)](./firestore_lite_pipelines.md#lessthan_01df3cf) | <b><i>(Public Preview)</i></b> Creates an expression that checks if an expression is less than a constant value. |
@@ -165,6 +166,7 @@ https://github.com/firebase/firebase-js-sdk
| [greaterThan(fieldName, value)](./firestore_lite_pipelines.md#greaterthan_65e2f32) | <b><i>(Public Preview)</i></b> Creates an expression that checks if a field's value is greater than a constant value. |
| [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_2e16acb) | <b><i>(Public Preview)</i></b> Creates an expression that checks if a field's value is greater than or equal to an expression. |
| [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_65e2f32) | <b><i>(Public Preview)</i></b> Creates an expression that checks if a field's value is greater than or equal to a constant value. |
| [isType(fieldName, type)](./firestore_lite_pipelines.md#istype_5da287e) | <b><i>(Public Preview)</i></b> Creates an expression that checks if the value in the specified field is of the given type. |
| [last(fieldName)](./firestore_lite_pipelines.md#last_e5b0480) | <b><i>(Public Preview)</i></b> Creates an aggregation that finds the last value of a field across multiple stage inputs. |
| [length\_2(fieldName)](./firestore_lite_pipelines.md#length_2_e5b0480) | <b><i>(Public Preview)</i></b> Creates an expression that calculates the length of a string, array, map, vector, or bytes. |
| [lessThan(fieldName, expression)](./firestore_lite_pipelines.md#lessthan_1e91657) | <b><i>(Public Preview)</i></b> Creates an expression that checks if a field's value is less than an expression. |
@@ -405,6 +407,7 @@ https://github.com/firebase/firebase-js-sdk
| [SetOptions](./firestore_lite_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad)<!-- -->, and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a <code>SetOptions</code> with <code>merge: true</code>. |
| [SortStageOptions](./firestore_lite_pipelines.md#sortstageoptions) | <b><i>(Public Preview)</i></b> Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort)<!-- -->. |
| [TimeGranularity](./firestore_lite_pipelines.md#timegranularity) | <b><i>(Public Preview)</i></b> Specify time granularity for expressions. |
| [Type](./firestore_lite_pipelines.md#type) | <b><i>(Public Preview)</i></b> An enumeration of the different types generated by the Firestore backend.<ul> <li>Numerics evaluate directly to backend representation (<code>int64</code> or <code>float64</code>), not JS <code>number</code>.</li> <li>JavaScript <code>Date</code> and firestore <code>Timestamp</code> objects strictly evaluate to <code>'timestamp'</code>.</li> <li>Advanced configurations parsing backend types (such as <code>decimal128</code>, <code>max_key</code> or <code>min_key</code> from BSON) are also incorporated in this union string type. Note that <code>decimal128</code> is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.</li> </ul> |
| [UnionStageOptions](./firestore_lite_pipelines.md#unionstageoptions) | <b><i>(Public Preview)</i></b> Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion)<!-- -->. |
| [UnnestStageOptions](./firestore_lite_pipelines.md#unneststageoptions) | <b><i>(Public Preview)</i></b> Represents the specific options available for configuring an <code>UnnestStage</code> within a pipeline. |
| [WhereStageOptions](./firestore_lite_pipelines.md#wherestageoptions) | <b><i>(Public Preview)</i></b> Options defining how a WhereStage is evaluated. See [Pipeline.where()](./firestore_pipelines.pipeline.md#pipelinewhere)<!-- -->. |
@@ -2399,6 +2402,43 @@ greaterThanOrEqual(field("quantity"), 10);
```
### isType(expression, type) {:#istype_27398ce}
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
>
Creates an expression that checks if the result of an expression is of the given type.
Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data.
<b>Signature:</b>
```typescript
export declare function isType(expression: Expression, type: Type): BooleanExpression;
```
#### Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. |
| type | [Type](./firestore_lite_pipelines.md#type) | The type to check for. |
<b>Returns:</b>
[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class)
A new `BooleanExpression` that evaluates to true if the expression's result is of the given type, false otherwise.
### Example
```typescript
// Check if the result of a calculation is a number
isType(add('count', 1), 'number')
```
### last(expression) {:#last_1138a27}
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
@@ -5014,6 +5054,43 @@ greaterThanOrEqual("score", 80);
```
### isType(fieldName, type) {:#istype_5da287e}
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
>
Creates an expression that checks if the value in the specified field is of the given type.
Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data.
<b>Signature:</b>
```typescript
export declare function isType(fieldName: string, type: Type): BooleanExpression;
```
#### Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| fieldName | string | The name of the field to check. |
| type | [Type](./firestore_lite_pipelines.md#type) | The type to check for. |
<b>Returns:</b>
[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class)
A new `BooleanExpression` that evaluates to true if the field's value is of the given type, false otherwise.
### Example
```typescript
// Check if the 'price' field is a floating point number (evaluating to true inside pipeline conditionals)
isType('price', 'float64');
```
### last(fieldName) {:#last_e5b0480}
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
@@ -7242,6 +7319,8 @@ trunc("rating", 2);
Creates an expression that returns the data type of the data in the specified field.
String inputs passed iteratively to this global function act as `field()` path lookups. If you wish to pass a string literal value, it must be wrapped: `type(constant("my_string"))`<!-- -->.
<b>Signature:</b>
```typescript
@@ -10728,6 +10807,21 @@ Specify time granularity for expressions.
export declare type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear';
```
## Type
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
>
An enumeration of the different types generated by the Firestore backend.
<ul> <li>Numerics evaluate directly to backend representation (`int64` or `float64`<!-- -->), not JS `number`<!-- -->.</li> <li>JavaScript `Date` and firestore `Timestamp` objects strictly evaluate to `'timestamp'`<!-- -->.</li> <li>Advanced configurations parsing backend types (such as `decimal128`<!-- -->, `max_key` or `min_key` from BSON) are also incorporated in this union string type. Note that `decimal128` is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.</li> </ul>
<b>Signature:</b>
```typescript
export declare type Type = 'null' | 'array' | 'boolean' | 'bytes' | 'timestamp' | 'geo_point' | 'number' | 'int32' | 'int64' | 'float64' | 'decimal128' | 'map' | 'reference' | 'string' | 'vector' | 'max_key' | 'min_key' | 'object_id' | 'regex' | 'request_timestamp';
```
## UnionStageOptions
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
@@ -101,6 +101,7 @@ field("optional_field").ifAbsent(field('default_field'))
| [ifError(catchValue)](./firestore_pipelines.expression.md#expressioniferror) | | <b><i>(Public Preview)</i></b> Creates an expression that returns the <code>catch</code> argument if there is an error, else return the result of this expression. |
| [isAbsent()](./firestore_pipelines.expression.md#expressionisabsent) | | <b><i>(Public Preview)</i></b> Creates an expression that returns <code>true</code> if the result of this expression is absent. Otherwise, returns <code>false</code> even if the value is <code>null</code>. |
| [isError()](./firestore_pipelines.expression.md#expressioniserror) | | <b><i>(Public Preview)</i></b> Creates an expression that checks if a given expression produces an error. |
| [isType(type)](./firestore_pipelines.expression.md#expressionistype) | | <b><i>(Public Preview)</i></b> Creates an expression that checks if the result of this expression is of the given type. |
| [join(delimiterExpression)](./firestore_pipelines.expression.md#expressionjoin) | | <b><i>(Public Preview)</i></b> Creates an expression that joins the elements of an array into a string. |
| [join(delimiter)](./firestore_pipelines.expression.md#expressionjoin) | | <b><i>(Public Preview)</i></b> Creates an expression that joins the elements of an array field into a string. |
| [last()](./firestore_pipelines.expression.md#expressionlast) | | <b><i>(Public Preview)</i></b> Creates an aggregation that finds the last value of an expression across multiple stage inputs. |
@@ -1977,6 +1978,42 @@ field("title").arrayContains(1).isError();
```
## Expression.isType()
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
>
Creates an expression that checks if the result of this expression is of the given type.
Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data.
<b>Signature:</b>
```typescript
isType(type: Type): BooleanExpression;
```
#### Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| type | [Type](./firestore_pipelines.md#type) | The type to check for. |
<b>Returns:</b>
[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class)
A new `BooleanExpression` that evaluates to true if the expression's result is of the given type, false otherwise.
### Example
```typescript
// Check if the 'price' field is specifically an integer (not just 'number')
field('price').isType('int64');
```
## Expression.join()
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
@@ -4463,6 +4500,8 @@ field("rating").trunc(constant(2));
Creates an expression that returns the data type of this expression's result, as a string.
This is evaluated on the backend. This means: 1. Generic typed elements (like `array<string>`<!-- -->) evaluate strictly to the primitive `'array'`<!-- -->. 2. Any custom `FirestoreDataConverter` mappings are ignored. 3. For numeric values, the backend does not yield the JavaScript `"number"` type; it evaluates precisely as `"int64"` or `"float64"`<!-- -->. 4. For date or timestamp objects, the backend evaluates to `"timestamp"`<!-- -->.
<b>Signature:</b>
```typescript
+94
View File
@@ -87,6 +87,7 @@ https://github.com/firebase/firebase-js-sdk
| [first(expression)](./firestore_pipelines.md#first_1138a27) | <b><i>(Public Preview)</i></b> Creates an aggregation that finds the first value of an expression across multiple stage inputs. |
| [greaterThan(expression, value)](./firestore_pipelines.md#greaterthan_01df3cf) | <b><i>(Public Preview)</i></b> Creates an expression that checks if an expression is greater than a constant value. |
| [greaterThanOrEqual(expression, value)](./firestore_pipelines.md#greaterthanorequal_01df3cf) | <b><i>(Public Preview)</i></b> Creates an expression that checks if an expression is greater than or equal to a constant value. |
| [isType(expression, type)](./firestore_pipelines.md#istype_27398ce) | <b><i>(Public Preview)</i></b> Creates an expression that checks if the result of an expression is of the given type. |
| [last(expression)](./firestore_pipelines.md#last_1138a27) | <b><i>(Public Preview)</i></b> Creates an aggregation that finds the last value of an expression across multiple stage inputs. |
| [length\_2(expression)](./firestore_pipelines.md#length_2_1138a27) | <b><i>(Public Preview)</i></b> Creates an expression that calculates the length of a string, array, map, vector, or bytes. |
| [lessThan(expression, value)](./firestore_pipelines.md#lessthan_01df3cf) | <b><i>(Public Preview)</i></b> Creates an expression that checks if an expression is less than a constant value. |
@@ -165,6 +166,7 @@ https://github.com/firebase/firebase-js-sdk
| [greaterThan(fieldName, value)](./firestore_pipelines.md#greaterthan_65e2f32) | <b><i>(Public Preview)</i></b> Creates an expression that checks if a field's value is greater than a constant value. |
| [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_2e16acb) | <b><i>(Public Preview)</i></b> Creates an expression that checks if a field's value is greater than or equal to an expression. |
| [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_65e2f32) | <b><i>(Public Preview)</i></b> Creates an expression that checks if a field's value is greater than or equal to a constant value. |
| [isType(fieldName, type)](./firestore_pipelines.md#istype_5da287e) | <b><i>(Public Preview)</i></b> Creates an expression that checks if the value in the specified field is of the given type. |
| [last(fieldName)](./firestore_pipelines.md#last_e5b0480) | <b><i>(Public Preview)</i></b> Creates an aggregation that finds the last value of a field across multiple stage inputs. |
| [length\_2(fieldName)](./firestore_pipelines.md#length_2_e5b0480) | <b><i>(Public Preview)</i></b> Creates an expression that calculates the length of a string, array, map, vector, or bytes. |
| [lessThan(fieldName, expression)](./firestore_pipelines.md#lessthan_1e91657) | <b><i>(Public Preview)</i></b> Creates an expression that checks if a field's value is less than an expression. |
@@ -411,6 +413,7 @@ https://github.com/firebase/firebase-js-sdk
| [SetOptions](./firestore_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad)<!-- -->, and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a <code>SetOptions</code> with <code>merge: true</code>. |
| [SortStageOptions](./firestore_pipelines.md#sortstageoptions) | <b><i>(Public Preview)</i></b> Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort)<!-- -->. |
| [TimeGranularity](./firestore_pipelines.md#timegranularity) | <b><i>(Public Preview)</i></b> Specify time granularity for expressions. |
| [Type](./firestore_pipelines.md#type) | <b><i>(Public Preview)</i></b> An enumeration of the different types generated by the Firestore backend.<ul> <li>Numerics evaluate directly to backend representation (<code>int64</code> or <code>float64</code>), not JS <code>number</code>.</li> <li>JavaScript <code>Date</code> and firestore <code>Timestamp</code> objects strictly evaluate to <code>'timestamp'</code>.</li> <li>Advanced configurations parsing backend types (such as <code>decimal128</code>, <code>max_key</code> or <code>min_key</code> from BSON) are also incorporated in this union string type. Note that <code>decimal128</code> is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.</li> </ul> |
| [UnionStageOptions](./firestore_pipelines.md#unionstageoptions) | <b><i>(Public Preview)</i></b> Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion)<!-- -->. |
| [UnnestStageOptions](./firestore_pipelines.md#unneststageoptions) | <b><i>(Public Preview)</i></b> Represents the specific options available for configuring an <code>UnnestStage</code> within a pipeline. |
| [WhereStageOptions](./firestore_pipelines.md#wherestageoptions) | <b><i>(Public Preview)</i></b> Options defining how a WhereStage is evaluated. See [Pipeline.where()](./firestore_pipelines.pipeline.md#pipelinewhere)<!-- -->. |
@@ -2405,6 +2408,43 @@ greaterThanOrEqual(field("quantity"), 10);
```
### isType(expression, type) {:#istype_27398ce}
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
>
Creates an expression that checks if the result of an expression is of the given type.
Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data.
<b>Signature:</b>
```typescript
export declare function isType(expression: Expression, type: Type): BooleanExpression;
```
#### Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. |
| type | [Type](./firestore_pipelines.md#type) | The type to check for. |
<b>Returns:</b>
[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class)
A new `BooleanExpression` that evaluates to true if the expression's result is of the given type, false otherwise.
### Example
```typescript
// Check if the result of a calculation is a number
isType(add('count', 1), 'number')
```
### last(expression) {:#last_1138a27}
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
@@ -5020,6 +5060,43 @@ greaterThanOrEqual("score", 80);
```
### isType(fieldName, type) {:#istype_5da287e}
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
>
Creates an expression that checks if the value in the specified field is of the given type.
Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data.
<b>Signature:</b>
```typescript
export declare function isType(fieldName: string, type: Type): BooleanExpression;
```
#### Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| fieldName | string | The name of the field to check. |
| type | [Type](./firestore_pipelines.md#type) | The type to check for. |
<b>Returns:</b>
[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class)
A new `BooleanExpression` that evaluates to true if the field's value is of the given type, false otherwise.
### Example
```typescript
// Check if the 'price' field is a floating point number (evaluating to true inside pipeline conditionals)
isType('price', 'float64');
```
### last(fieldName) {:#last_e5b0480}
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
@@ -7248,6 +7325,8 @@ trunc("rating", 2);
Creates an expression that returns the data type of the data in the specified field.
String inputs passed iteratively to this global function act as `field()` path lookups. If you wish to pass a string literal value, it must be wrapped: `type(constant("my_string"))`<!-- -->.
<b>Signature:</b>
```typescript
@@ -10803,6 +10882,21 @@ Specify time granularity for expressions.
export declare type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear';
```
## Type
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
>
An enumeration of the different types generated by the Firestore backend.
<ul> <li>Numerics evaluate directly to backend representation (`int64` or `float64`<!-- -->), not JS `number`<!-- -->.</li> <li>JavaScript `Date` and firestore `Timestamp` objects strictly evaluate to `'timestamp'`<!-- -->.</li> <li>Advanced configurations parsing backend types (such as `decimal128`<!-- -->, `max_key` or `min_key` from BSON) are also incorporated in this union string type. Note that `decimal128` is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.</li> </ul>
<b>Signature:</b>
```typescript
export declare type Type = 'null' | 'array' | 'boolean' | 'bytes' | 'timestamp' | 'geo_point' | 'number' | 'int32' | 'int64' | 'float64' | 'decimal128' | 'map' | 'reference' | 'string' | 'vector' | 'max_key' | 'min_key' | 'object_id' | 'regex' | 'request_timestamp';
```
## UnionStageOptions
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
@@ -141,6 +141,8 @@ export {
trim,
ltrim,
rtrim,
type,
isType,
stringConcat,
stringIndexOf,
stringRepeat,
@@ -193,7 +195,6 @@ export {
arraySum,
split,
timestampTruncate,
type,
AliasedExpression,
Field,
Constant,
@@ -204,5 +205,6 @@ export {
Selectable,
BooleanExpression,
AggregateFunction,
TimeGranularity
TimeGranularity,
Type
} from '../../src/lite-api/expressions';
+4 -2
View File
@@ -96,6 +96,8 @@ export {
trim,
ltrim,
rtrim,
type,
isType,
stringConcat,
stringIndexOf,
stringRepeat,
@@ -162,7 +164,6 @@ export {
arraySum,
timestampTruncate,
split,
type,
Expression,
AliasedExpression,
Field,
@@ -173,7 +174,8 @@ export {
ExpressionType,
AliasedAggregate,
Selectable,
TimeGranularity
TimeGranularity,
Type
} from './lite-api/expressions';
export { _internalPipelineToExecutePipelineRequestProto } from './remote/internal_serializer';
+158 -48
View File
@@ -55,6 +55,39 @@ export type ExpressionType =
| 'ListOfExpressions'
| 'AliasedExpression';
/**
* @beta
*
* An enumeration of the different types generated by the Firestore backend.
*
* <ul>
* <li>Numerics evaluate directly to backend representation (`int64` or `float64`), not JS `number`.</li>
* <li>JavaScript `Date` and firestore `Timestamp` objects strictly evaluate to `'timestamp'`.</li>
* <li>Advanced configurations parsing backend types (such as `decimal128`, `max_key` or `min_key` from BSON) are also incorporated in this union string type. Note that `decimal128` is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.</li>
* </ul>
*/
export type Type =
| 'null'
| 'array'
| 'boolean'
| 'bytes'
| 'timestamp'
| 'geo_point'
| 'number'
| 'int32'
| 'int64'
| 'float64'
| 'decimal128'
| 'map'
| 'reference'
| 'string'
| 'vector'
| 'max_key'
| 'min_key'
| 'object_id'
| 'regex'
| 'request_timestamp';
/**
* Converts a value to an Expression, Returning either a Constant, MapFunction,
* ArrayFunction, or the input itself (if it's already an expression).
@@ -1266,6 +1299,53 @@ export abstract class Expression implements ProtoValueSerializable, UserData {
return new FunctionExpression('rtrim', args, 'rtrim');
}
/**
* @beta
* Creates an expression that returns the data type of this expression's result, as a string.
*
* @remarks
* This is evaluated on the backend. This means:
* 1. Generic typed elements (like `array<string>`) evaluate strictly to the primitive `'array'`.
* 2. Any custom `FirestoreDataConverter` mappings are ignored.
* 3. For numeric values, the backend does not yield the JavaScript `"number"` type; it evaluates
* precisely as `"int64"` or `"float64"`.
* 4. For date or timestamp objects, the backend evaluates to `"timestamp"`.
*
* @example
* ```typescript
* // Get the data type of the value in field 'title'
* field('title').type()
* ```
*
* @returns A new `Expression` representing the data type.
*/
type(): FunctionExpression {
return new FunctionExpression('type', [this]);
}
/**
* @beta
* Creates an expression that checks if the result of this expression is of the given type.
*
* @remarks Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data.
*
* @example
* ```typescript
* // Check if the 'price' field is specifically an integer (not just 'number')
* field('price').isType('int64');
* ```
*
* @param type - The type to check for.
* @returns A new `BooleanExpression` that evaluates to true if the expression's result is of the given type, false otherwise.
*/
isType(type: Type): BooleanExpression {
return new FunctionExpression(
'is_type',
[this, constant(type)],
'isType'
).asBoolean();
}
/**
* @beta
* Creates an expression that concatenates string expressions together.
@@ -2791,22 +2871,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData {
return new FunctionExpression('timestamp_trunc', args);
}
/**
* @beta
* Creates an expression that returns the data type of this expression's result, as a string.
*
* @example
* ```typescript
* // Get the data type of the value in field 'title'
* field('title').type()
* ```
*
* @returns A new `Expression` representing the data type.
*/
type(): FunctionExpression {
return new FunctionExpression('type', [this]);
}
// TODO(new-expression): Add new expression method definitions above this line
/**
@@ -7056,6 +7120,84 @@ export function rtrim(
return fieldOrExpression(expr).rtrim(valueToTrim);
}
/**
* @beta
* Creates an expression that returns the data type of the data in the specified field.
*
* @remarks
* String inputs passed iteratively to this global function act as `field()` path lookups.
* If you wish to pass a string literal value, it must be wrapped: `type(constant("my_string"))`.
*
* @example
* ```typescript
* // Get the data type of the value in field 'title'
* type('title')
* ```
*
* @returns A new `Expression` representing the data type.
*/
export function type(fieldName: string): FunctionExpression;
/**
* @beta
* Creates an expression that returns the data type of an expression's result.
*
* @example
* ```typescript
* // Get the data type of a conditional expression
* type(conditional(exists('foo'), constant(1), constant(true)))
* ```
*
* @returns A new `Expression` representing the data type.
*/
export function type(expression: Expression): FunctionExpression;
export function type(
fieldNameOrExpression: string | Expression
): FunctionExpression {
return fieldOrExpression(fieldNameOrExpression).type();
}
/**
* @beta
* Creates an expression that checks if the value in the specified field is of the given type.
*
* @remarks Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data.
*
* @example
* ```typescript
* // Check if the 'price' field is a floating point number (evaluating to true inside pipeline conditionals)
* isType('price', 'float64');
* ```
*
* @param fieldName - The name of the field to check.
* @param type - The type to check for.
* @returns A new `BooleanExpression` that evaluates to true if the field's value is of the given type, false otherwise.
*/
export function isType(fieldName: string, type: Type): BooleanExpression;
/**
* @beta
* Creates an expression that checks if the result of an expression is of the given type.
*
* @remarks Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data.
*
* @example
* ```typescript
* // Check if the result of a calculation is a number
* isType(add('count', 1), 'number')
* ```
*
* @param expression - The expression to check.
* @param type - The type to check for.
* @returns A new `BooleanExpression` that evaluates to true if the expression's result is of the given type, false otherwise.
*/
export function isType(expression: Expression, type: Type): BooleanExpression;
export function isType(
fieldNameOrExpression: string | Expression,
type: Type
): BooleanExpression {
return fieldOrExpression(fieldNameOrExpression).isType(type);
}
/**
* @beta
*
@@ -9446,38 +9588,6 @@ export function timestampTruncate(
);
}
/**
* @beta
* Creates an expression that returns the data type of the data in the specified field.
*
* @example
* ```typescript
* // Get the data type of the value in field 'title'
* type('title')
* ```
*
* @returns A new `Expression` representing the data type.
*/
export function type(fieldName: string): FunctionExpression;
/**
* @beta
* Creates an expression that returns the data type of an expression's result.
*
* @example
* ```typescript
* // Get the data type of a conditional expression
* type(conditional(exists('foo'), constant(1), constant(true)))
* ```
*
* @returns A new `Expression` representing the data type.
*/
export function type(expression: Expression): FunctionExpression;
export function type(
fieldNameOrExpression: string | Expression
): FunctionExpression {
return fieldOrExpression(fieldNameOrExpression).type();
}
// TODO(new-expression): Add new top-level expression function definitions above this line
/**
@@ -154,7 +154,8 @@ import {
PipelineSnapshot,
timestampTruncate,
split,
type
type,
isType
} from '../util/pipeline_export';
use(chaiAsPromised);
@@ -4507,6 +4508,75 @@ apiDescribe.skipClassic('Pipelines', persistence => {
});
});
it('supports isType', async () => {
const result = await execute(
firestore
.pipeline()
.collection(randomCol)
.limit(1)
.replaceWith(
map({
int: constant(1),
float: constant(1.1),
str: constant('a string'),
bool: constant(true),
null: constant(null),
geoPoint: constant(new GeoPoint(0.1, 0.2)),
timestamp: constant(new Timestamp(123456, 0)),
bytes: constant(Bytes.fromUint8Array(new Uint8Array([1, 2, 3]))),
docRef: constant(doc(firestore, randomCol.path, 'bar')),
vector: constant(vector([1, 2, 3])),
map: map({
numberK: 1,
stringK: 'a string'
}),
array: array([1, '2', true])
})
)
.select(
isType(field('int'), 'int64').as('isInt64'),
isType(field('int'), 'number').as('isInt64IsNumber'),
isType(field('int'), 'decimal128').as('isInt64IsDecimal128'),
field('float').isType('float64').as('isFloat64'),
field('float').isType('number').as('isFloat64IsNumber'),
field('float').isType('decimal128').as('isFloat64IsDecimal128'),
isType('str', 'string').as('isStr'),
isType('int', 'string').as('isNumStr'),
field('bool').isType('boolean').as('isBool'),
isType('null', 'null').as('isNull'),
field('geoPoint').isType('geo_point').as('isGeoPoint'),
isType('timestamp', 'timestamp').as('isTimestamp'),
field('bytes').isType('bytes').as('isBytes'),
isType('docRef', 'reference').as('isDocRef'),
field('vector').isType('vector').as('isVector'),
isType('map', 'map').as('isMap'),
field('array').isType('array').as('isArray'),
field('str').isType('int64').as('isStrNum')
)
);
expectResults(result, {
isInt64: true,
isInt64IsNumber: true,
isInt64IsDecimal128: false,
isFloat64: true,
isFloat64IsNumber: true,
isFloat64IsDecimal128: false,
isStr: true,
isNumStr: false,
isBool: true,
isNull: true,
isGeoPoint: true,
isTimestamp: true,
isBytes: true,
isDocRef: true,
isVector: true,
isMap: true,
isArray: true,
isStrNum: false
});
});
// TODO(new-expression): Add new expression tests above this line
});
@@ -66,6 +66,7 @@ import {
ifError,
isAbsent,
isError,
isType,
or,
map,
length,
@@ -134,6 +135,7 @@ import {
toLower,
toUpper,
trim,
type,
byteLength,
arrayGet,
abs,
@@ -4125,6 +4127,133 @@ describe.skipClassic('Firestore Pipelines', () => {
indexOfByte: 1
});
});
it('testType', async () => {
const snapshot = await execute(
firestore
.pipeline()
.collection(randomCol.path)
.replaceWith(
map({
int: constant(1),
float: constant(1.1),
str: constant('a string'),
bool: constant(true),
null: constant(null),
geoPoint: constant(new GeoPoint(0.1, 0.2)),
timestamp: constant(new Timestamp(123456, 0)),
bytes: constant(
Bytes.fromUint8Array(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0]))
),
docRef: constant(doc(firestore, 'foo', 'bar')),
vector: constant(vector([1, 2, 3])),
map: map({
'number': 1,
'string': 'a string'
}),
list: array([1, '2', true])
})
)
.select(
type(field('int')).as('int'),
field('float').type().as('float'),
type('str').as('str'),
field('bool').type().as('bool'),
type('null').as('null'),
field('geoPoint').type().as('geoPoint'),
type('timestamp').as('timestamp'),
field('bytes').type().as('bytes'),
type('docRef').as('docRef'),
field('vector').type().as('vector'),
type('map').as('map'),
field('list').type().as('list')
)
.limit(1)
);
expectResults(snapshot, {
int: 'int64',
float: 'float64',
str: 'string',
bool: 'boolean',
null: 'null',
geoPoint: 'geo_point',
timestamp: 'timestamp',
bytes: 'bytes',
docRef: 'reference',
vector: 'vector',
map: 'map',
list: 'array'
});
});
it('testIsType', async () => {
const snapshot = await execute(
firestore
.pipeline()
.collection(randomCol.path)
.replaceWith(
map({
int: constant(1),
float: constant(1.1),
str: constant('a string'),
bool: constant(true),
null: constant(null),
geoPoint: constant(new GeoPoint(0.1, 0.2)),
timestamp: constant(new Timestamp(123456, 0)),
bytes: constant(Bytes.fromUint8Array(new Uint8Array([1, 2, 3]))),
docRef: constant(doc(firestore, randomCol.path, 'bar')),
vector: constant(vector([1, 2, 3])),
map: map({
numberK: 1,
stringK: 'a string'
}),
array: array([1, '2', true])
})
)
.select(
isType(field('int'), 'int64').as('isInt64'),
isType(field('int'), 'number').as('isInt64IsNumber'),
isType(field('int'), 'decimal128').as('isInt64IsDecimal128'),
field('float').isType('float64').as('isFloat64'),
field('float').isType('number').as('isFloat64IsNumber'),
field('float').isType('decimal128').as('isFloat64IsDecimal128'),
isType('str', 'string').as('isStr'),
isType('int', 'string').as('isNumStr'),
field('bool').isType('boolean').as('isBool'),
isType('null', 'null').as('isNull'),
field('geoPoint').isType('geo_point').as('isGeoPoint'),
isType('timestamp', 'timestamp').as('isTimestamp'),
field('bytes').isType('bytes').as('isBytes'),
isType('docRef', 'reference').as('isDocRef'),
field('vector').isType('vector').as('isVector'),
isType('map', 'map').as('isMap'),
field('array').isType('array').as('isArray'),
field('str').isType('int64').as('isStrNum')
)
.limit(1)
);
expectResults(snapshot, {
isInt64: true,
isInt64IsNumber: true,
isInt64IsDecimal128: false,
isFloat64: true,
isFloat64IsNumber: true,
isFloat64IsDecimal128: false,
isStr: true,
isNumStr: false,
isBool: true,
isNull: true,
isGeoPoint: true,
isTimestamp: true,
isBytes: true,
isDocRef: true,
isVector: true,
isMap: true,
isArray: true,
isStrNum: false
});
});
it('test reverse', async () => {
const snapshot = await execute(