Standalone Functions
Feature Overview
Every method in TypeScript SDKs generated by Speakeasy is also available as a standalone function. This alternative API is ideal for browser or serverless environments, where bundlers can optimize applications by tree-shaking unused functionality. This includes unused methods, Zod schemas, encoding helpers, and response handlers. As a result, the application’s final bundle size is dramatically smaller and grows very gradually as more of the generated SDK is used.
Using methods through the main SDK class remains a valid and generally more ergonomic option. Standalone functions are an optimization designed for specific types of applications.
Usage
Step 1: Import the Core Class and Function
First, import the Core
SDK class for authentication and setup, along with the
required standalone function. An SDK named Todo
, for example, might look like
this:
import { TodoCore } from "todo/core.js";import { todosCreate } from "todo/funcs/todosCreate.js";
The Core
SDK class is optimized for tree-shaking, and can be reused throughout
the application.
Step 2: Instantiate the Core Class
Create an instance of the Core
class with the required configuration (e.g., an
API Key):
const todoSDK = new TodoCore({apiKey: "TODO_API_KEY",});
Step 3: Call the Standalone Function & Handle the Result
Invoke the standalone function, passing the core instance the first parameter. Handle the result using a switch statement for comprehensive error handling:
async function run() {const res = await todosCreate(todoSDK);switch (true) {case res.ok:// Successful response is processed later.break;case res.error instanceof SDKValidationError:// Display validation errors in a readable format.return console.log(res.error.pretty());case res.error instanceof Error:// Handle general errors.return console.log(res.error);default:// Ensure all error cases are exhaustively handled.res.error satisfies never;throw new Error("Unexpected error case: " + res.error);}const { value: todo } = res;// Handle the successful result.console.log(todo);}run();
Result Types
Standalone functions differ from SDK methods in that they return a
Result<Value, Error>
type to capture known errors and document them through
the type system. This approach avoids throwing errors, allowing application code
to maintain clear control flow while making error handling a natural part of the
application code.
NOTE
The term “known errors” is used because standalone functions and
JavaScript code can still throw unexpected errors (e.g., TypeError
,
RangeError
, and DOMException
). While exhaustively catching all errors may
be addressed in future SDK versions, there’s significant value in capturing
most errors and converting them into values.
Another reason for this programming style is that these functions are commonly used in front-end applications where throwing exceptions is often discouraged. React and similar frameworks promote this approach to ensure components can render appropriate content in all states—loading, success, and error.
Thus, the general pattern when calling standalone functions looks like this:
import { Core } from "<sdk-package-name>";import { fetchSomething } from "<sdk-package-name>/funcs/fetchSomething.js";const client = new Core();async function run() {const result = await fetchSomething(client, { id: "123" });if (!result.ok) {// You can throw the error or handle it. It's your choice now.throw result.error;}console.log(result.value);}run();
Note that, unlike a try-catch block where errors are of type unknown
(or any
depending on TypeScript settings), result.error
in this example has a
specific, explicit type.