Type system

A TypeDB database consists of a schema and data.

A schema consists of types & rules.

TypeDB databases have static typing with strict type hierarchy achieved by inheritance.

Everything that is not permitted by the schema is considered forbidden in the database.

Types

A type represents a set of constraints on the interpretation of data.

A type for a data instance is like a class for an object in OOP.

A definition of a type in a schema of a database sets:

  • type hierarchy — every user-defined type has only one parent or supertype.

  • constraints — what a type can do: what role to play, what attributes it can own, what value type it has (attribute types only), and what roles it relates (relation types only).

A type can be addressed by its label (name). A type label is unique in a schema of a database.

We can define a new type only as a subtype of an existing one.

A new empty database has a set of built-in types. These built-in types are called root types because all user-defined types will be subtypes (direct or non-direct) of those root types.

Table 1. Root (built-in) types
Root type label A subtype of the root type An instance of data of a subtype

entity

Entity type

Instance of entity type

relation

Relation type

Instance of relation type

attribute

Attribute type

Instance of attribute type

All root types are abstract types.

That’s why when we say entity type, we usually mean a subtype of the entity root type. In the same way, we can address relation type or attribute type instead of mentioning subtypes of the root types.

Inheritance

A type can subtype another type. As a result, the subtype inherits all the attributes owned and roles played by its supertype.

Roles can be inherited and even overridden as a part of relation inheritance.

Type can only have a single supertype.

Types can be subtypes of other subtypes, resulting in a type hierarchy.

See simple example

For example, business-unit subtypes user-group, which subtypes subject, which subtypes entity root type. Also, person subtypes user, that subtypes subject:

  • entity

    • subject

      • user group

        • business unit

      • user

        • person

In TypeQL we can define these types with the following query:

define

subject sub entity;
user-group sub subject;
business-unit sub user-group;
user sub subject;
person sub user;

There is a strict hierarchy of types, so the whole typing system of a TypeDB database can always be represented by three independent trees with one of the root types at the top of each tree.

See hierarchy trees example

For example, a schema with the following types:

  • entity

    • person

    • vehicle

      • car

      • motorcycle

      • bicycle

  • relation

    • owning

    • using

      • driving

      • traveling

  • attribute

    • model

    • name

      • full-name

      • nickname

can be visualized as following type hierarchy:

root types trees

Abstract types

An abstract type can’t be instantiated (we can’t insert an instance of data of this type). All we can do with an abstract type is to subtype it.

All root types are abstract types.

The opposite of an abstract type is a concrete type.

All user-defined types are concrete types by default.

To see how to define an abstract type see the Define types section of the Define schema page.

Thing type

An internal type called thing can be used to address all types (both built-in and user-defined) or instances of all types (effectively — all data).

All types are subtypes of the thing, including the root types.

Types hierarchy

The thing internal type will be deprecated in one of the upcoming versions and deleted in TypeDB version 3.0.

Consider using entity, attribute, or relation built-in types instead.

To produce the same result as the above example, use the following query:

match $s sub $t; {$t type entity;} or {$t type relation;} or {$t type attribute;};

Entity types

Entity types (or subtypes of the entity root type) represent the classification of independent objects in the data model of our business domain.

Instance of data of an entity type represents a standalone object that exists in our data model independently.

Instance of an entity type doesn’t have a value. It is usually addressed by its ownership over attribute instances and/or roles played in relation instances.

An object modeled with an entity type might practically require other entities to exist, such as a car that cannot exist without its parts, but can be conceptualized without reference to those other entities: a car can be imagined without considering its parts.

For more information on how to define an entity type see the Defining schema page.

Relation types

Relation types (or subtypes of the relation root type) represent relationships between types. Relation types have roles.

Other types can play roles in relations if it’s mentioned in their definition. An instance of another type can be a role player for a role in the instance of a relation.

An instance of a relation can be uniquely addressed by a combination of its type, owned attributes, and role players.

A relation type must specify at least one role. A relation cannot be conceptualized without at least some of its role players.

See the group-membership example

For example, given the schema:

define

group-membership sub relation,
    relates user-group,
    relates group-member;

user-group sub entity
    plays group-membership:user-group;

subject sub entity,
    plays group-membership:group-member;
user sub subject;

group-membership is a relation type that defines user-group and group-member roles. The user-group role is to be played by a user-group entity type whereas the group-member role is to be played by a subject type and all its subtypes entities.

For more information on how to define a relation type see the Defining schema page.

Attribute types

Attribute types (or subtypes of the attribute root type) represent properties that other types can own.

Attribute types have a value type, and instances of attribute types have a value. This value is fixed and unique for every given instance of the attribute type.

Other types can own an attribute type. That means that instances of these other types can own an instance of this attribute type. This usually means that an object in our domain has a property with the matching value.

An instance of an attribute type can be uniquely addressed by its type and value.

There can’t be a second instance of the same type with the same value.

Multiple types can own the same attribute type — and different instances of the same type or different types can share ownership of the same attribute instance.

For more information on how to define an attribute subtype see the Defining schema page.

See example

Given the schema:

define

name sub attribute, value string;

person sub entity,
    owns name;

An instance of an attribute type name with a value "Bob" can be owned by:

  • no one (no instance of the person type owns the instance of the name type with value "Bob"),

  • one particular person (there is one person with such a name),

  • or multiple people (there are multiple people with the name Bob. All of the pesron type instances have ownership of the same instance of the name type with the value "Bob").

The feature of an attribute type owning another attribute type will be deprecated in one of the upcoming versions and deleted in TypeDB version 3.0.

Learn more

This was the first page of the Fundamentals section.

We recommend finishing the rest of the section:

To learn more about TypeQL, see the TypeQL documentation.