Type Mapping

Usually, your source data (e.g. from a database or an external endpoint) will not exactly match the types defined in your schema. In the example app, a Customer references Contracts internally through IDs, whereas the schema naturally allows retrieving the full Contract objects from the Customer.

To handle this in a type-safe way, the @ts directive provides a way to map GraphQL types to TypeScript types. First, you’ll need to add the @ts directive to your schema (it’s recommended to put all directives into schema/directives.gql):

directive @ts(
  type: String!
  inputType: String
  from: String
) on OBJECT | INTERFACE | ENUM | SCALAR

By creating a source interface CustomerSource in TypeScript which knows about the contractIds, and adding a mapping via the @ts directive, you will receive and return CustomerSource objects instead of Customer objects in your resolvers:

# In all field resolvers of the "Customer" resolver,
# the "source" argument shall be of type "CustomerSource".
# Likewise, all field resolvers that should resolve to a GraphQL "Customer",
# the return type shall be of TypeScript type "CustomerSource".
# "CustomerSource" shall be imported from "../types"
# (relative to the location of the generated code).
type Customer @ts(type: "CustomerSource" from: "../types") {
  ...
}

The QueryResolver can now safely return customer data as CustomerSource objects. In turn, the CustomerResolver is then able to resolve the contracts field by using the internal customer data in a type-safe way, because it receives CustomerSource objects in the data-argument of it’s resolver functions.

Note how almost none of the types in src/resolvers/*.ts have to be made explicit, which makes the code very readable and greatly reduces the chance of programmer errors.

Input Type Mapping

For some scalars, it is useful to be able to return multiple types in resolvers. A DateTime-scalar may be returned as a JavaScript Date-object or as a ISO-string because the serializer accepts both, so it is useful to map the GraphQL DateTime to string | Date internally using @ts(type: "...").

When a scalar is used as an input, you’ll likely know the specific type being returned by the deserializer. For example, if you know the deserializer for DateTime always returns a Date-object, you should add inputType: "Date" to your @ts directive:

# Field resolvers resolving to GraphQL "DateTime" may return "string | number | Date".
# Input fields of GraphQL type "DateTime" shall be of TypeScript type "Date".
scalar DateTime @ts(type: "string | number | Date", inputType: "Date")