# Object Types

*Object types* are the primary components of a Gel schema. They are analogous to SQL *tables* or ORM *models*, and consist of [properties](https://docs.geldata.com/reference/datamodel/properties.md#ref-datamodel-props) and [links](https://docs.geldata.com/reference/datamodel/links.md#ref-datamodel-links).

## Properties

Properties are used to attach primitive/scalar data to an object type. For the full documentation on properties, see [Properties](https://docs.geldata.com/reference/datamodel/properties.md#ref-datamodel-props).

```sdl
type Person {
  email: str;
}
```

Using in a query:

```edgeql
select Person {
  email
};
```

## Links

Links are used to define relationships between object types. For the full documentation on links, see [Links](https://docs.geldata.com/reference/datamodel/links.md#ref-datamodel-links).

```sdl
type Person {
  email: str;
  best_friend: Person;
}
```

Using in a query:

```edgeql
select Person {
  email,
  best_friend: {
    email
  }
};
```

## ID

There's no need to manually declare a primary key on your object types. All object types automatically contain a property `id` of type `UUID` that's *required*, *globally unique*, *readonly*, and has an index on it. The `id` is assigned upon creation and cannot be changed.

Using in a query:

```edgeql
select Person { id };
select Person { email } filter .id = <uuid>'123e4567-e89b-...';
```

## Abstract types

Object types can either be *abstract* or *non-abstract*. By default all object types are non-abstract. You can't create or store instances of abstract types (a.k.a. mixins), but they're a useful way to share functionality and structure among other object types.

```sdl
abstract type HasName {
  first_name: str;
  last_name: str;
}
```

## Inheritance

Object types can *extend* other object types. The extending type (AKA the *subtype*) inherits all links, properties, indexes, constraints, etc. from its *supertypes*.

```sdl
abstract type HasName {
  first_name: str;
  last_name: str;
}

type Person extending HasName {
  email: str;
  best_friend: Person;
}
```

Using in a query:

```edgeql
select Person {
  first_name,
  email,
  best_friend: {
    last_name
  }
};
```

## Multiple Inheritance

Object types can extend more than one type — that's called *multiple inheritance*. This mechanism allows building complex object types out of combinations of more basic types.

> Note: Gel's multiple inheritance should not be confused with the multiple inheritance of C++ or Python, where the complexity usually arises from fine-grained mixing of logic. Gel's multiple inheritance is structural and allows for natural composition.

```sdl-diff
   abstract type HasName {
     first_name: str;
     last_name: str;
   }

+  abstract type HasEmail {
+    email: str;
+  }

-  type Person extending HasName {
+  type Person extending HasName, HasEmail {
-    email: str;
     best_friend: Person;
  }
```

If multiple supertypes share links or properties, those properties must be of the same type and cardinality.

## Defining object types

This section describes the syntax to declare object types in your schema.

### Syntax

```sdl-synopsis
[abstract] type <TypeName> [extending <supertype> [, ...] ]
[ "{"
    [ <annotation-declarations> ]
    [ <property-declarations> ]
    [ <link-declarations> ]
    [ <constraint-declarations> ]
    [ <index-declarations> ]
    ...
  "}" ]
```

#### Description

This declaration defines a new object type with the following options:

`abstract`:
If specified, the created type will be *abstract*.



`<TypeName>`:
The name (optionally module-qualified) of the new type.



`extending <supertype> [, ...]`:
Optional clause specifying the *supertypes* of the new type.

Use of `extending` creates a persistent type relationship between the new subtype and its supertype(s). Schema modifications to the supertype(s) propagate to the subtype.

References to supertypes in queries will also include objects of the subtype.

If the same *link* name exists in more than one supertype, or is explicitly defined in the subtype and at least one supertype, then the data types of the link targets must be *compatible*. If there is no conflict, the links are merged to form a single link in the new type.



These sub-declarations are allowed in the `Type` block:

`<annotation-declarations>`:
Set object type [annotation](https://docs.geldata.com/reference/datamodel/annotations.md#ref-eql-sdl-annotations) to a given *value*.



`<property-declarations>`:
Define a concrete [property](https://docs.geldata.com/reference/datamodel/properties.md#ref-eql-sdl-props) for this object type.



`<link-declarations>`:
Define a concrete [link](https://docs.geldata.com/reference/datamodel/links.md#ref-eql-sdl-links) for this object type.



`<constraint-declarations>`:
Define a concrete [constraint](https://docs.geldata.com/reference/datamodel/constraints.md#ref-eql-sdl-constraints) for this object type.



`<index-declarations>`:
Define an [index](https://docs.geldata.com/reference/datamodel/indexes.md#ref-eql-sdl-indexes) for this object type.



## DDL commands

This section describes the low-level DDL commands for creating, altering, and dropping object types. You typically don't need to use these commands directly, but knowing about them is useful for reviewing migrations.

### Create type

Define a new object type.

```edgeql-synopsis
[ with <with-item> [, ...] ]
create [abstract] type <name> [ extending <supertype> [, ...] ]
[ "{" <subcommand>; [...] "}" ] ;

# where <subcommand> is one of

  create annotation <annotation-name> := <value>
  create link <link-name> ...
  create property <property-name> ...
  create constraint <constraint-name> ...
  create index on <index-expr>
```

#### Description

The command `create type` defines a new object type for use in the current branch.

If *name* is qualified with a module name, then the type is created in that module, otherwise it is created in the current module. The type name must be distinct from that of any existing schema item in the module.

#### Parameters

Most sub-commands and options of this command are identical to the [SDL object type declaration](https://docs.geldata.com/reference/datamodel/objects.md#ref-eql-sdl-object-types-syntax), with some additional features listed below:

`with <with-item> [, ...]`:
Alias declarations.

The `with` clause allows specifying module aliases that can be referenced by the command. See [With block](https://docs.geldata.com/reference/reference/edgeql/with.md#ref-eql-statements-with) for more information.



The following subcommands are allowed in the `create type` block:

`create annotation <annotation-name> := <value>`:
Set object type `<annotation-name>` to `<value>`.

See [`create annotation`](https://docs.geldata.com/reference/datamodel/annotations.md#statement::create-annotation) for details.



`create link <link-name> ...`:
Define a new link for this object type. See [`create link`](https://docs.geldata.com/reference/datamodel/links.md#statement::create-link) for details.



`create property <property-name> ...`:
Define a new property for this object type. See [`create property`](https://docs.geldata.com/reference/datamodel/properties.md#statement::create-property) for details.



`create constraint <constraint-name> ...`:
Define a concrete constraint for this object type. See [`create constraint`](https://docs.geldata.com/reference/datamodel/constraints.md#statement::create-constraint) for details.



`create index on <index-expr>`:
Define a new [index](https://docs.geldata.com/reference/datamodel/indexes.md#ref-datamodel-indexes) using *index-expr* for this object type. See [`create index`](https://docs.geldata.com/reference/datamodel/indexes.md#statement::create-index) for details.



#### Example

Create an object type `User`:

```edgeql
create type User {
    create property name: str;
};
```

### Alter type

Change the definition of an object type.

```edgeql-synopsis
[ with <with-item> [, ...] ]
alter type <name>
[ "{" <subcommand>; [...] "}" ] ;

[ with <with-item> [, ...] ]
alter type <name> <subcommand> ;

# where <subcommand> is one of

  rename to <newname>
  extending <parent> [, ...]
  create annotation <annotation-name> := <value>
  alter annotation <annotation-name> := <value>
  drop annotation <annotation-name>
  create link <link-name> ...
  alter link <link-name> ...
  drop link <link-name> ...
  create property <property-name> ...
  alter property <property-name> ...
  drop property <property-name> ...
  create constraint <constraint-name> ...
  alter constraint <constraint-name> ...
  drop constraint <constraint-name> ...
  create index on <index-expr>
  drop index on <index-expr>
```

#### Description

The command `alter type` changes the definition of an object type. *name* must be a name of an existing object type, optionally qualified with a module name.

#### Parameters

`with <with-item> [, ...]`:
Alias declarations.

The `with` clause allows specifying module aliases that can be referenced by the command. See [With block](https://docs.geldata.com/reference/reference/edgeql/with.md#ref-eql-statements-with) for more information.



`<name>`:
The name (optionally module-qualified) of the type being altered.



`extending <parent> [, ...]`:
Alter the supertype list. The full syntax of this subcommand is:

```edgeql-synopsis
extending <parent> [, ...]
  [ first | last | before <exparent> | after <exparent> ]
```

This subcommand makes the type a subtype of the specified list of supertypes. The requirements for the parent-child relationship are the same as when creating an object type.

It is possible to specify the position in the parent list using the following optional keywords:

- `first` – insert parent(s) at the beginning of the parent list,
- `last` – insert parent(s) at the end of the parent list,
- `before <parent>` – insert parent(s) before an existing *parent*,
- `after <parent>` – insert parent(s) after an existing *parent*.



`alter annotation <annotation-name>;`:
Alter object type annotation `<annotation-name>`. See [`alter annotation`](https://docs.geldata.com/reference/datamodel/annotations.md#statement::alter-annotation) for details.



`drop annotation <annotation-name>`:
Remove object type `<annotation-name>`. See [`drop annotation`](https://docs.geldata.com/reference/datamodel/annotations.md#statement::drop-annotation) for details.



`alter link <link-name> ...`:
Alter the definition of a link for this object type. See [`alter link`](https://docs.geldata.com/reference/datamodel/links.md#statement::alter-link) for details.



`drop link <link-name>`:
Remove a link item from this object type. See [`drop link`](https://docs.geldata.com/reference/datamodel/links.md#statement::drop-link) for details.



`alter property <property-name> ...`:
Alter the definition of a property item for this object type. See [`alter property`](https://docs.geldata.com/reference/datamodel/properties.md#statement::alter-property) for details.



`drop property <property-name>`:
Remove a property item from this object type. See [`drop property`](https://docs.geldata.com/reference/datamodel/properties.md#statement::drop-property) for details.



`alter constraint <constraint-name> ...`:
Alter the definition of a constraint for this object type. See [`alter constraint`](https://docs.geldata.com/reference/datamodel/constraints.md#statement::alter-constraint) for details.



`drop constraint <constraint-name>;`:
Remove a constraint from this object type. See [`drop constraint`](https://docs.geldata.com/reference/datamodel/constraints.md#statement::drop-constraint) for details.



`drop index on <index-expr>`:
Remove an [index](https://docs.geldata.com/reference/datamodel/indexes.md#ref-datamodel-indexes) defined as *index-expr* from this object type. See [`drop index`](https://docs.geldata.com/reference/datamodel/indexes.md#statement::drop-index) for details.



All the subcommands allowed in the `create type` block are also valid subcommands for the `alter type` block.

#### Example

Alter the `User` object type to make `name` required:

```edgeql
alter type User {
    alter property name {
        set required;
    }
};
```

### Drop type

Remove the specified object type from the schema.

```edgeql-synopsis
drop type <name> ;
```

#### Description

The command `drop type` removes the specified object type from the schema. All subordinate schema items defined on this type, such as links and indexes, are removed as well.

#### Example

Remove the `User` object type:

```edgeql
drop type User;
```

|                                                                                                                                                |
| ---------------------------------------------------------------------------------------------------------------------------------------------- |
| **See also**                                                                                                                                   |
| [Introspection > Object types](https://docs.geldata.com/reference/datamodel/introspection/objects.md#ref-datamodel-introspection-object-types) |
| [Cheatsheets > Object types](https://docs.geldata.com/resources/cheatsheets/objects.md#ref-cheatsheet-object-types)                            |

