Guide
The GraphQL emitter (@typespec/graphql) generates GraphQL Schema Definition Language (SDL) from TypeSpec sources. The generated schemas can be used with any GraphQL server implementation.
Fundamental Concepts
Section titled “Fundamental Concepts”The GraphQL emitter transforms TypeSpec models, operations, and enums into their GraphQL equivalents. To generate a valid GraphQL schema, your TypeSpec must follow certain conventions.
Schemas
Section titled “Schemas”A GraphQL schema is defined by applying the @schema decorator to a TypeSpec namespace. All types and operations within the namespace will be emitted to a single GraphQL schema file.
import "@typespec/graphql";
using GraphQL;
@schemanamespace MyService {// Types and operations go here
}You can optionally specify a name for the schema, which will be used in the output filename:
@schema(#{ name: "petstore" })namespace PetStore {// ...
}This will generate a file named petstore.graphql.
Object Types
Section titled “Object Types”TypeSpec models are transformed into GraphQL object types. For example:
model Pet { id: string; name: string; age: int32;}Becomes:
type Pet { id: String! name: String! age: Int!}Note that all fields are non-nullable (!) by default in GraphQL. See Nullability for how to make fields nullable.
Operations
Section titled “Operations”GraphQL supports three operation types: queries, mutations, and subscriptions. Use the corresponding decorators to specify the operation kind:
@query op getPet(id: string): Pet;@query op listPets(): Pet[];
@mutation op createPet(name: string, age: int32): Pet;@mutation op deletePet(id: string): boolean;
@subscription op onPetCreated(): Pet;This generates:
type Query { getPet(id: String!): Pet! listPets: [Pet!]!}
type Mutation { createPet(name: String!, age: Int!): Pet! deletePet(id: String!): Boolean!}
type Subscription { onPetCreated: Pet!}Input Types
Section titled “Input Types”When a model is used as an operation parameter (mutation input), the emitter automatically generates a corresponding GraphQL input type with an Input suffix:
model Pet { name: string; age: int32;}
@mutation op createPet(input: Pet): Pet;Generates:
input PetInput { name: String! age: Int!}
type Mutation { createPet(input: PetInput!): Pet!}TypeSpec enums map to GraphQL enums with member names converted to CONSTANT_CASE:
enum PetStatus { Available, Pending, Sold,}Becomes:
enum PetStatus { AVAILABLE PENDING SOLD}Nullability
Section titled “Nullability”By default, all GraphQL types are non-nullable. To make a field or return type nullable, use TypeSpec’s union with null:
model Pet { id: string; nickname: string | null; // Nullable field}
@query op findPet(id: string): Pet | null; // Nullable returnGenerates:
type Pet { id: String! nickname: String # No ! means nullable}
type Query { findPet(id: String!): Pet # Nullable return}For nullable array elements, the emitter handles Array<T | null> patterns:
model SearchResult { pets: (Pet | null)[]; # Array with nullable elements}Generates:
type SearchResult { pets: [Pet]! # Non-null array, nullable elements}Interfaces
Section titled “Interfaces”GraphQL interfaces allow you to define a common set of fields that multiple types can implement. Use the @graphqlInterface decorator:
@graphqlInterface(#{ interfaceOnly: true })model Node { id: string;}
@compose(Node)model Pet { ...Node; name: string;}Generates:
interface Node { id: String!}
type Pet implements Node { id: String! name: String!}The interfaceOnly option prevents the model from also being emitted as an object type (useful for abstract interfaces like Node).
Type Mappings
Section titled “Type Mappings”| TypeSpec Type | GraphQL Type |
|---|---|
string | String |
boolean | Boolean |
int32 | Int |
float32, float64 | Float |
GraphQL.ID | ID |
T[] | [T!]! |
T | null | T (nullable) |
Example Configuration
Section titled “Example Configuration”To use the GraphQL emitter, add it to your tspconfig.yaml:
emit: - "@typespec/graphql"The emitter will generate .graphql files in your output directory.