typespec.io

2 min read Original article ↗

Design APIs

Design your data up front and generate schemas, API specifications, client / server code, docs, and more.

import "@typespec/http";

using Http;

model Store {

name: string;

address: Address;

}

model Address {

street: string;

city: string;

}

@route("/stores")

interface Stores {

list(@query filter: string): Store[];

read(@path id: Store): Store;

}

openapi: 3.0.0

info:

title: (title)

version: 0.0.0

tags: []

paths:

/stores:

get:

operationId: Stores_list

parameters:

- name: filter

in: query

required: true

schema:

type: string

responses:

'200':

description: The request has succeeded.

content:

application/json:

schema:

type: array

items:

$ref: '#/components/schemas/Store'

/stores/{id}:

get:

operationId: Stores_read

parameters:

- name: id

in: path

required: true

schema:

$ref: '#/components/schemas/Store'

responses:

'200':

description: The request has succeeded.

content:

application/json:

schema:

$ref: '#/components/schemas/Store'

components:

schemas:

Address:

type: object

required:

- street

- city

properties:

street:

type: string

city:

type: string

Store:

type: object

required:

- name

- address

properties:

name:

type: string

address:

$ref: '#/components/schemas/Address'

Why TypeSpec

API-First for developers

With TypeSpec, remove the handwritten files that slow you down, and generate standards-compliant API schemas in seconds.

Lightweight language for defining APIs

Inspired by TypeScript, TypeSpec is a minimal language that helps developers describe API shapes in a familiar way.

Learn about TypeSpec for REST APIs →

Easy integration with your toolchain

Write TypeSpec, emit to various formats and integrate with their ecosystems.

~ /my-project tsp init

? Select a template

Empty project

> REST API

import "@typespec/http";

using Http;

model Pet {

name: string;

age: int32;

}

model Store {

name: string;

address: Address;

}

model Address {

street: string;

city: string;

}

@route("/pets")

interface Pets {

list(@query filter: string): Pet[];

create(@body pet: Pet): Pet;

read(@path id: string): Pet;

}

@route("/stores")

interface Stores {

list(@query filter: string): Store[];

read(@path id: string): Store;

}

import "./common.tsp";

namespace MyOrg.Accounts;

using MyOrg.Types;

model Account {

id: id;

firstName: string;

lastName: string;

createdAt: utcDateTime;

// Use imported type by name only when using `using`

ssn: ssn;

// Or use the fully qualified name

email: MyOrg.Types.email;

balance: Amount;

}

model Amount {

value: decimal128;

currency: Currency;

}

// Create your own error types by extending the Error type

model AccountError is Error<"duplicate-account" | "invalid-account">;

op createAccount(account: Account): Account;

op charge(accountId: id, amount: Amount): void | AccountError;

extern dec group(target: TypeSpec.Reflection.Model, name: valueof string);

import { DecoratorContext, EmitContext, Model, resolvePath } from "@typespec/compiler";

export async function $onEmit(context: EmitContext) {

const outputDir = resolvePath(context.emitterOutputDir, "hello.txt");

await context.program.host.writeFile(outputDir, "hello world!");

}

const groupKey = Symbol.for("my-library/group");

export function $group(context: DecoratorContext, target: Model, value: string) {

context.program.stateMap(groupKey).set(target, value);

}

Start your TypeSpec journey

Install the TypeSpec CLI or check out the playground to get started.