# 2608 Typing B1ef9c8b

> Typing

- Skill: `tools-only/2608-typing-b1ef9c8b` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add tools-only/2608-typing-b1ef9c8b`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tools-only/2608-typing-b1ef9c8b/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Research & Search
- Author: tools-only (https://skillmd.com/u/tools-only)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/tools-only/2608-typing-b1ef9c8b

---

# Typing

Alloy provides precise static types for commands and ask via `.pyi` stubs.

- Use `@command(output=T)` for a typed result `T`.
- If you omit `output`, the command returns `str` (and `Awaitable[str]` for async).
- Parameters are preserved (ParamSpec), so your decorated command keeps the same args.
- Streaming always yields text chunks (`str`).

Basics
```python
from alloy import command, ask

@command(output=float)
def extract_price(text: str) -> str:
    return f"Extract price from: {text}"

price: float = extract_price("the price is 5.99")

# No output → str
@command
def summarize(text: str) -> str:
    return f"Summarize: {text}"

summary: str = summarize("hello")
```

Async
```python
from dataclasses import dataclass
from typing import Awaitable, AsyncIterable
from alloy import command

@dataclass
class User:
    name: str
    id: int

@command(output=User)
async def fetch_user(name: str) -> str:
    return f"Find user named {name} and return JSON"

user_awaitable: Awaitable[User] = fetch_user()
# after await -> User

# Streaming
chunks: AsyncIterable[str] = fetch_user.stream()

# Convenience
user_awaitable2: Awaitable[User] = fetch_user.async_()
```

Ask namespace
```python
from typing import Iterable, AsyncIterable
from alloy import ask

text: str = ask("Explain in one sentence.")
sync_stream: Iterable[str] = ask.stream("Explain briefly.")
async_stream: AsyncIterable[str] = ask.stream_async("Explain briefly.")
```

Notes
- Import from `alloy`: `from alloy import command, ask`. Importing through submodules bypasses the stubs.
- Alloy does not infer from your function’s return annotation. The decorated function must be annotated `-> str` (it returns a prompt string). The decorator’s `output` parameter controls the command’s return type; when omitted, the return type is `str`.


## IDE Experience

```python
from dataclasses import dataclass
from alloy import command

@dataclass
class ArticleSummary:
    title: str
    key_points: list[str]
    reading_time_minutes: int

@command(output=ArticleSummary)
def summarize(text: str) -> str:  # returns a prompt string
    return f"Summarize: {text}"

result = summarize("...")
result.  # IDE autocompletes: title, key_points, reading_time_minutes
```

