Shared Types Package
In this page:
Core Concept
A shared-types package is a small, dependency-free TypeScript package that holds interfaces and types used by two or more other packages — most commonly a frontend and a backend that need to agree on API request/response shapes.
Example: Core Concept
// packages/shared-types/index.ts
export interface CreateUserRequest {
email: string;
password: string;
}
console.log("A dependency-free package holding types shared across consumers");
Basic Setup
A basic setup is just a package.json with a main/types field pointing at compiled output, a tsconfig.json set to emit declaration files, and an index.ts that re-exports every shared type.
Example: Basic Setup
// package.json: { "main": "dist/index.js", "types": "dist/index.d.ts" }
// tsconfig.json: { "compilerOptions": { "declaration": true } }
console.log("index.ts re-exports every shared type from one entry point");
Typed Example
A typed example might export interface CreateUserRequest { email: string; password: string } from the shared package, then import that exact same interface in both an Express route handler and a React form component.
Example: Typed Example
export interface CreateUserRequest {
email: string;
password: string;
}
// Imported identically in both an Express handler and a React form
const req: CreateUserRequest = { email: "[email protected]", password: "secret" };
console.log(req);
Project Usage
In a real project, publishing this package to a private npm registry (or referencing it via workspace protocol in a monorepo) means a backend API change to a shared type immediately shows up as a compile error in the frontend that consumes it.
Example: Project Usage
// A backend type change surfaces as a frontend compile error immediately
// once both packages import from the same shared-types package.
console.log("Publishing/workspace-linking keeps both sides in sync");
Best Practices
Keep the shared-types package free of runtime logic and framework-specific imports (no React, no Express) so it stays lightweight and usable from literally any consumer, including non-JavaScript tooling that reads its .d.ts files.
Example: Best Practices
// Keep shared-types free of React/Express imports and runtime logic.
export interface ApiError {
message: string;
code: number;
}
console.log("Framework-free types stay usable from any consumer");
Chapter Quiz — Complete all 5 topics to unlock
0/5 topics done
Complete these topics first: