A TypeScript Language Service Plugin that provides IDE-level awareness for "use …" directives such as "use server", "use client", "use cache", and more.
- 🎯 Directive Detection: Automatically detects directives at module scope and within exported functions
- 💡 Inline Hints: Displays small inline annotations like
<use server>next to declarations and imports - 📝 Hover Tooltips: Provides detailed hover information for directive-marked exports
- ✅ Validation: Error checking for invalid directives with helpful error messages
- 🔍 Import Tracking: Recognizes when imported functions originate from directive-marked exports
- 🔌 Extensible: Third-party packages can add custom directives via declaration merging
- 🎨 Framework Agnostic: No runtime dependencies or directive semantics - pure static analysis
- 📦 Universal Support: Works with
.js,.ts,.jsx, and.tsxfiles
While the plugin comes with built-in support for a minimal set of common directives, it can be extended by third-party packages. The built-in supported directives are:
"use server""use client""use no memo""use ..."(with optional provider and options syntax)
npm install typescript-plugin-directives
# or
pnpm add typescript-plugin-directivesAdd the plugin to your tsconfig.json:
{
"compilerOptions": {
"plugins": [
{
"name": "typescript-plugin-directives"
}
]
}
}Enable inlay hints in VS Code (.vscode/settings.json):
{
"editor.inlayHints.enabled": "on",
"typescript.inlayHints.parameterNames.enabled": "all"
}Restart the TypeScript server:
- Open the Command Palette (
Cmd+Shift+P/Ctrl+Shift+P) - Select "TypeScript: Restart TS Server"
Place a directive at the top of your file - all exports inherit it:
"use server";
export async function addTodo(text: string) {
// This function has "use server" directive
}
export async function deleteTodo(id: string) {
// This function also has "use server" directive
}IDE Display: Both functions show <use server> inline hint
export async function addTodo(formData: FormData) {
"use server";
// ... server-side logic
}IDE Display: addTodo <use server>
Hover Tooltip:
"use server"
addTodo(formData: FormData): Promise<void>This export is marked with the "use server" directive.
import { addTodo } from "./actions";IDE Display: addTodo <use server>
Hover Tooltip:
Imported symbol "addTodo" originates from a "use server" export.
export async function getData() {
"use cache: server; ttl=3600";
// Cached with server provider, 1 hour TTL
}IDE Display: getData <use cache>
The plugin provides comprehensive validation for directives:
- Type an unknown directive like
"use unknown"and you'll see a red squiggle - The error message lists all valid directives from the type system
- Third-party directives are automatically included in validation
- Directives must be placed at the beginning of a module or function body
- Multiple consecutive directives at the start are allowed (e.g.,
"use client"followed by"use no memo") - If a directive appears after other statements, you'll get an error:
- Module-level:
Directive "use server" must be at the beginning of the module body - Function-level:
Directive "use server" must be at the beginning of the function body
- Module-level:
Example of incorrect position:
const x = 1;
"use server"; // ❌ Error: must be at the beginning
export function action() {
const y = 2;
"use server"; // ❌ Error: must be at the beginning
}Example of valid position:
"use client";
"use no memo"; // ✅ Multiple consecutive directives allowed
import { something } from "./other";export function action() {
"use server"; // ✅ First statement in function
const y = 2;
}Third-party packages can extend the plugin by adding custom directives via declaration merging:
// my-framework/global.d.ts
declare global {
interface DirectiveRegistry {
"use my-custom": never;
"use another-directive": never;
}
}
export {};{
"name": "my-framework",
"types": "./global.d.ts",
"files": ["global.d.ts"]
}When users install your package, they'll automatically get:
- ✅ Autocomplete for your custom directives
- ✅ Validation (errors for typos)
- ✅ Hover tooltips
- ✅ Inlay hints
The plugin:
- Scans your code for directive strings at the top of files or functions
- Tracks directives across imports/exports
- Reads the global
Directivetype from TypeScript's type system to validate directives - Provides IDE features through TypeScript Language Service API
The Directive type is a union of all registered directives, extended via declaration merging. This means the plugin automatically picks up any custom directives added by third-party packages!
- Node.js >= 24
- TypeScript >= 5.0.0
Contributions are welcome! Please see CONTRIBUTING.md for details.
# Clone and install
pnpm install
# Build packages
pnpm build
# Run tests
pnpm test
# Run tests with coverage
pnpm test:coverage
# Lint and format code
pnpm lint
pnpm lint:fix
# Add a changeset for your changes
pnpm changesetMIT