How to Use Spectral in TypeScript
Blog
Olivia Brown  

How to Use Spectral in TypeScript

So, you want cleaner APIs. Fewer bugs. Better documentation. And you want all of that without losing your mind. Good news. Spectral is here to help. And yes, it plays very nicely with TypeScript.

TLDR: Spectral is a flexible linter for JSON and YAML files. It is often used to validate OpenAPI and AsyncAPI specs. In TypeScript, you can use Spectral to programmatically lint API definitions, create custom rules, and enforce consistent standards across your projects. Setup is simple, customization is powerful, and it helps catch problems early.

Let’s break it down. And let’s make it fun.


What Is Spectral?

Spectral is a linter. But not for your TypeScript code.

It lints:

  • OpenAPI specs
  • AsyncAPI specs
  • JSON files
  • YAML files

Think of it as ESLint. But for API definitions.

If your OpenAPI file says something weird like this:

  • Missing descriptions
  • No response examples
  • Bad naming conventions
  • Inconsistent error formats

Spectral will gently (or aggressively) point it out.


Why Use Spectral with TypeScript?

You could just run Spectral from the command line. And that’s fine.

But when you use Spectral inside a TypeScript project, things get more powerful.

Now you can:

  • Lint dynamically generated schemas
  • Integrate validation into build tools
  • Create automated API pipelines
  • Write custom rules with full type safety

And let’s be honest. We like type safety. It makes us feel warm inside.


Step 1: Install Spectral

Start simple.

npm install @stoplight/spectral-core
npm install @stoplight/spectral-rulesets
npm install @stoplight/spectral-parsers

You might also install:

npm install @stoplight/spectral-formats

Now you’re ready.


Step 2: Basic Usage in TypeScript

Here’s a minimal example.

import { Spectral } from "@stoplight/spectral-core";
import { oas } from "@stoplight/spectral-rulesets";
import { Document, Parsers } from "@stoplight/spectral-core";

async function run() {
  const spectral = new Spectral();
  spectral.setRuleset(oas);

  const apiDefinition = `
openapi: 3.0.0
info:
  title: My API
  version: 1.0.0
paths: {}
`;

  const document = new Document(apiDefinition, Parsers.Yaml);
  const results = await spectral.run(document);

  console.log(results);
}

run();

What’s happening here?

  • We create a Spectral instance
  • We load the built-in OpenAPI ruleset
  • We parse a YAML string
  • We run the linter
  • We print the issues

Simple. Clean. Effective.


What Do the Results Look Like?

Spectral returns an array of results.

Each result contains:

  • Code – which rule failed
  • Message – what went wrong
  • Path – where it happened
  • Severity – how bad it is

Example result:

{
  code: "info-description",
  message: "Info object must have a description.",
  path: ["info"],
  severity: 1
}

Now you can:

  • Fail a CI build if severity is high
  • Log custom messages
  • Group errors by type

You are in control.


Step 3: Using Custom Rules

This is where things get exciting.

You can define your own rules.

Let’s say every endpoint must have a summary. No exceptions.

spectral.setRules({
  "require-operation-summary": {
    description: "Operations must have a summary",
    given: "$.paths[*][*]",
    then: {
      field: "summary",
      function: "truthy"
    },
    severity: 1
  }
});

Now Spectral will complain if any operation is missing a summary.

This is fantastic for:

  • Large teams
  • Shared API standards
  • Enterprise consistency

Understanding “given” and “then”

Every rule has two key parts.

given – where to look.
then – what to check.

The given field uses JSONPath. It’s like a treasure map for your schema.

Example:

  • $.paths[*][*] → every operation
  • $.components.schemas[*] → every schema

The then part defines the validation function.

Common built-in functions:

  • truthy – must exist
  • pattern – must match regex
  • enumeration – must match allowed values
  • schema – must match JSON Schema

It’s like building logic blocks.


Step 4: Creating Custom Functions

Want more power?

Write your own validation function in TypeScript.

import { createRulesetFunction } from "@stoplight/spectral-core";

const startsWithUppercase = createRulesetFunction(
  {
    input: { type: "string" }
  },
  function (input) {
    if (!input[0] || input[0] !== input[0].toUpperCase()) {
      return [
        {
          message: "Must start with uppercase letter"
        }
      ];
    }
  }
);

Then use it in your rules:

spectral.setRules({
  "summary-uppercase": {
    given: "$.paths[*][*].summary",
    then: {
      function: startsWithUppercase
    }
  }
});

Now your API summaries must be classy. Proper. Uppercase.

TypeScript helps here.

You get:

  • Auto-complete
  • Type checking
  • Safer refactoring

Step 5: Linting Files Instead of Strings

Usually, you’ll lint actual files.

import { readFileSync } from "fs";

const file = readFileSync("./openapi.yaml", "utf8");
const document = new Document(file, Parsers.Yaml);

const results = await spectral.run(document);

Perfect for:

  • Pre-commit hooks
  • CLI tools
  • Build scripts

You can even wrap this in a custom command.


Integrating Spectral into a CI Pipeline

This is where Spectral shines.

In your CI system:

  • Load your API spec
  • Run Spectral
  • Fail if errors exist

Example:

if (results.some(r => r.severity === 0)) {
  process.exit(1);
}

Now broken API definitions never reach production.

Your future self will thank you.


Best Practices

Let’s keep things clean and practical.

1. Start with Built-In Rules

Don’t reinvent the wheel. Use the OpenAPI ruleset first.

2. Add Team-Specific Rules

Enforce naming conventions. Require examples. Standardize error formats.

3. Keep Rules Small and Clear

One rule. One responsibility.

4. Use TypeScript Types Everywhere

Type your inputs. Type your outputs. Catch mistakes early.

5. Version Control Your Ruleset

Treat it like production code. Because it is.


Common Mistakes

Let’s avoid pain.

  • Overloading rules – too many checks in one rule
  • Ignoring warnings – they exist for a reason
  • Not documenting custom rules
  • Skipping CI integration

Spectral works best when it’s automatic. Not optional.


When Should You Use Spectral?

Use Spectral when:

  • You publish APIs to other teams
  • You maintain public APIs
  • Your documentation must stay consistent
  • You care about quality

If your API is “just for internal use,” you still benefit.

Because messy APIs grow fast. Very fast.


Why Developers Love It

Spectral is:

  • Flexible
  • Scriptable
  • TypeScript-friendly
  • CI-ready

It doesn’t force a rigid structure. It gives you building blocks.

You design your own API quality system.


Final Thoughts

Spectral with TypeScript is a powerful combo.

You get:

  • Automated API validation
  • Customizable rules
  • Type-safe extensions
  • Clean CI integration

It’s not complicated.

Install it. Run it. Add a few rules. Improve gradually.

Over time, your APIs become clearer. More predictable. More professional.

And the best part?

Most mistakes get caught before anyone else sees them.

That’s the kind of quiet productivity boost every developer loves.

Now go lint your APIs. Your future documentation will look amazing.