Types

The foundation of EdgeQL is EdgeDB’s rigorous typesystem. There is a set of EdgeQL operators and functions for changing, introspecting, and filtering by types.

Type expressions

Type expressions are exactly what they sound like: EdgeQL expressions that refer to a type. Most commonly, these are simply the names of established types: str, int64, BlogPost, etc. Arrays and tuples have a dedicated type syntax.

Type

Syntax

Array

array<x>

Tuple (unnamed)

tuple<x, y, z>

Tuple (named)

tuple<foo: x, bar: y>

For additional details on type syntax, see Schema > Primitive Types.

Type casting

Type casting is used to convert primitive values into another type. Casts are indicated with angle brackets containing a type expression.

  1. db>
  1. select <str>10;
  1. {"10"}
  1. db>
  1. select <bigint>10;
  1. {10n}
  1. db>
  1. select <array<str>>[1, 2, 3];
  1. {['1', '2', '3']}
  1. db>
  1. select <tuple<str, float64, bigint>>(1, 2, 3);
  1. {('1', 2, 3n)}

Type casts are useful for declaring literals for types like datetime, uuid, and int16 that don’t have a dedicated syntax.

  1. db>
  1. select <datetime>'1999-03-31T15:17:00Z';
  1. {<datetime>'1999-03-31T15:17:00Z'}
  1. db>
  1. select <int16>42;
  1. {42}
  1. db>
  1. select <uuid>'89381587-705d-458f-b837-860822e1b219';
  1. {89381587-705d-458f-b837-860822e1b219}

There are limits to what values can be cast to a certain type. In some cases two types are entirely incompatible, like bool and int64; in other cases, the source data must be in a particular format, like casting str to datetime.

  1. db>
  1. select <BlogPost>10;
  1. QueryError: cannot cast 'std::int64' to 'default::BlogPost'
  1. db>
  1. select <int64>'asdf';
  1. InvalidValueError: invalid input syntax for type std::int64: "asdf"
  1. db>
  1. select <int16>100000000000000n;
  1. NumericOutOfRangeError: std::int16 out of range

For a comprehensive table of castability, see Standard Library > Casts.

Type intersections

Type casts can only be used on primitive expressions, not object type expressions. Every object stored in the database is strongly and immutably typed; you can’t simply convert an object to an object of a different type.

All elements of a given set have the same type; however, in the context of sets of objects, this may be misleading. A set of Animal objects may contain instances of multiple subtypes, like Cat and Dog.

  1. db>
  1. select Animal;
  1. {
  2. default::Dog {id: 9d2ce01c-35e8-11ec-acc3-83b1377efea0},
  3. default::Dog {id: 3bfe4900-3743-11ec-90ee-cb73d2740820},
  4. default::Cat {id: b0e0dd0c-35e8-11ec-acc3-abf1752973be},
  5. }

We can use the type intersection operator to restrict the elements of a set by subtype.

  1. db>
  1. select Animal[is Dog];
  1. {
  2. default::Dog {id: 9d2ce01c-35e8-11ec-acc3-83b1377efea0},
  3. default::Dog {id: 3bfe4900-3743-11ec-90ee-cb73d2740820},
  4. }

Logically, this computes the intersection of the Animal and Dog sets; since only Dog objects occur in both sets, this can be conceptualized as a “filter” that removes all elements that aren’t of type Dog.

Type checking

The [is foo] “type intersection” syntax should not be confused with the type checking operator is.

  1. db>
  1. select 5 is int64;
  1. {true}
  1. db>
  1. select {3.14, 2.718} is not int64;
  1. {true, true}
  1. db>
  1. select Animal is Dog;
  1. {true, true, false}

The type of any expression can be extracted with the typeof operator. This can be used in any expression that expects a type.

  1. db>
  1. select <typeof 5>'100';
  1. {100}
  1. db>
  1. select "tuna" is typeof "trout";
  1. {true}

Introspection

The entire typesystem of EdgeDB is stored inside EdgeDB. All types are introspectable as instances of the schema::Type type. For a set of introspection examples, see Guides > Introspection.