Este texto é sobre minha experiência tentando replicar a geração de código (e tipos) para interações entre **frontend e backend, se você prefere partir pro código, pode pular pra parte da implementação.

Conteudo:

Motivação

Há uns anos atras, trabalhei em um projeto GraphQL, eu amei demais as vantagens dele (apesar de reconhecer alguns de seus defeitos), mas uma das que mais se destacou foi a de ter um schema de tudo que o backend disponibiliza como API, o schema no GraphQL é algo assim:

type Query {
  me: User
}

type User {
  id: ID
  name: String
}

No GraphQL, o schema informa todos os 'endpoints' de consulta disponíveis (type Query), suas rotas (me) , argumentos (se tiverem) e retornos (User). Além de ser uma documentação, o schema também me possibilita gerar código. **Por exemplo, aplicando o graphql-code-generator no schema acima eu consigo gerar um código similar a este em Typescript:

type Query = {
  me: User
}

type User = {
	id: string
	name: string
}

Porém quando precisei voltar a mexer em REST, lembrei que não era costume fazer essa geração de código, e, além disso, eu não conhecia muito sobre como documentar/formalizar APIs RESTful, mas eu me lembrava de já ter lidado com o Swagger pra isso.

Swagger e a OpenAPI Spec

Se você trabalha com REST com certeza já ouviu falar do Swagger, ele é uma ferramenta que te permite gerar uma página interativa com a documentação da sua API REST, uma das coisas que você pode não ter pensado é que o Swagger não foi feito pra ser usado somente com uma UI.

O Swagger é baseado em uma especificação, chamada de OpenAPI Specification (OAS), dela ele gera a sua interface amigável. Geralmente a OAS é escrita ou gerada em JSON e te permite fazer as mesmas coisas que você faria com o schema GraphQL: documentar toda a sua API e também gerar 'coisas' com base nela. Um exemplo da especificação OAS fica assim:

{
  "openapi": "3.0.0",
  "info": {
    "title": "My API Documentation",
    "description": "My API documentation and playground",
    "version": "1.0",
    "contact": {}
  },
  "components": {
    "schemas": {
      "User": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
					"name": { "type": "string" }
        },
        "required": ["id", "name"]
      }
    }
    },
  "paths": {
    "/me": {
      "get": {
        "operationId": "getMe",
        "summary": "Returns the logged user data",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Logged user info",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          }
        }
      }
    }
  }
}

É só um "pouquinho" maior que o schema do GraphQL, porém ela te permite documentar mais algumas coisas, como por exemplo os tipos de autenticações disponíveis na sua API.

OpenAPI Typescript Codegen