Catch errors early with type checking

FQL is a statically typed query language. Every value has a specific data type. You can only call FQL methods that are valid for a value’s type.

Fauna’s type checking feature helps you catch FQL type mismatches before evaluation. This helps prevent runtime errors that can be hard to diagnose and fix.

Type checking by example

The following examples show Fauna handles FQL queries with type checking enabled and disabled. The examples use the Fauna Dashboard and Fauna’s demo data.

  1. In the Dashboard Shell, ensure type checking is enabled. If enabled, a check mark appears next to Typecheck.

    Type checking enabled

  2. Run the following FQL query to create a document in the Product collection.

    // Create a document with a specific `id`
    Product.create({
      id: "392886847463751747",
      name: "limes",
      description: "Organic, 1 ct",
      price: 0.65
    })

    The query uses create() to specify a document id. This lets you more easily fetch the document in later examples.

  3. With type checking enabled, attempt to update the document using the following query. The query:

    • Uses byId() to fetch the document you created.

    • Calls update() on the returned document.

    // Update the document
    Product.byId("392886847463751747")
      .update({
        description: "Organic, 2 ct",
      })

    The query is unsafe and returns an error:

    invalid_query
    
    error: Type `Null` does not have field `update`
    at *query*:3:4
      |
    3 |   .update({
      |    ^^^^^^
      |
    hint: Use the ! or ?. operator to handle the null case
    at *query*:2:35
      |
    2 | Product.byId("392886847463751747")!
      |                                   +
      |

    byId() returns a Document or a NullDoc, which indicates the requested document doesn’t exist. NullDocs always contain a null value.

    The query passes this value to update(), which only accepts a Document. The query doesn’t safely handle cases in which byId() may return a NullDoc.

    To fix this, you can append one of the following postfix operators to byId():

  4. Add the ?. postfix operator and rerun the query:

    // Update the document
    Product.byId("392886847463751747")
      ?.update({
        description: "Organic, 2 ct",
      })

    The query now runs successfully.

  5. In the Dashboard Shell, click Typecheck to disable type checking.

  6. Rerun the previous unsafe query:

    // Update the document
    Product.byId("392886847463751747")
      .update({
        description: "Organic, 2 ct",
      })

    With type checking disabled, the unsafe query runs successfully. While this may seem more convenient, it adds risk.

    Now, the query won’t return an error until byId() returns a NullDoc. If this does happen, it’s likely to occur later in the development process — possibly when the application is already in production.

  7. To test this out, delete the document and rerun the unsafe query with type checking disabled:

    // Delete the document
    Product.byId("392886847463751747")
      .delete()
    
    // Attempt to update the deleted document
    Product.byId("392886847463751747")
      .update({
        description: "Organic, 2 ct",
      })

    The query now returns an error:

    document_not_found
    
    error: Collection `Product` does not contain document with id 392886847463751747.
    at *query*:6:13
      |
    6 | Product.byId("392886847463751747")
      |             ^^^^^^^^^^^^^^^^^^^^^^
      |

Enable type checking for a database

When you can create a database in the Fauna Dashboard, you can enable type checking using the Static Typing option. If wanted, you can later edit the database to change this option.

Enable type checking for a child database

You can enable type checking for a child database using <Database>.update():

Database.byName( "childDB" )
  ?.update(
    { typechecked: true }
  )

The typecheck property set using a Fauna client driver overrides this setting.

Enable type checking in the driver

You can enable type checking in Fauna’s client drivers at two levels:

  • Configure the driver’s client instance to enable type checking on all queries by default. For example:

    ...
    const clientConfig = {
      typecheck: true,
      ...
    };
    
    const client = new Client(clientConfig);
    ...
  • Configure type checking on specific query calls. For example:

    ...
    const queryOptions = {
      typecheck: true,
      ...
    };
    
    const response = await client.query(fql`"Hello World!"`, queryOptions);
    ...

To use type checking in a driver, type checking must be enabled in the database.

Type checking for UDFs and other database entities

If you disable type checking for a database, Fauna does not type check the database’s:

  • User-defined function (UDF) definitions

  • FQL expressions, such as predicate functions, in role and access provider definitions

If you use type checking, you can use a UDF definition’s signature field to explicitly type the UDF when you create it:

function TypeTest(x: Number, y: Number): Number {
  x + y
}

Learn more

See the Static typing reference documentation for more detailed information about type checking.

Is this article helpful? 

Tell Fauna how the article can be improved:
Visit Fauna's forums or email docs@fauna.com

Thank you for your feedback!