# Rust Types And Apis

> Use for trait bounds, generics, trait objects, newtypes, typestate, conversion boundaries, public API design, and crate-facing Rust interfaces. Use when this capability is needed.

- Skill: `tomevault-io/rust-types-and-apis` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/rust-types-and-apis`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/rust-types-and-apis/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/rust-types-and-apis

---


# Rust Types and APIs

Use this when the real question is how much of the design should be expressed
in types, traits, and public signatures.

## Working stance

- Make invalid states hard to represent before adding runtime checks.
- Keep public APIs narrower than internal helper code.
- Prefer concrete types until abstraction pressure is real.
- Use trait objects for extension seams and heterogeneity, not by reflex.
- Prefer typed domains and borrowed read-only inputs over stringly or
  collection-specific signatures.
- Accept broad inputs; return precise outputs.

## Decision surface

- Generics: the caller should stay generic and one concrete type flows through
  each call site.
- `dyn Trait`: runtime heterogeneity, plugin seams, or monomorphization costs
  matter more than static dispatch.
- Newtype: domain distinction matters and misuse should not compile.
- Typestate: operation order is finite and important enough to encode.
- Sealed trait: downstream implementations would weaken invariants.
- `AsRef` or `Into` inputs: caller flexibility helps without hiding semantics.
- `&str` or `&[T]` inputs: prefer them over `&String` or `&Vec<T>` when the
  callee only reads.

## Red flags

- public APIs expose internal helper traits or incidental generic parameters,
- public APIs accept `&String` or `&Vec<T>` where `&str` or `&[T]` would do,
- public functions take two or more `bool` parameters (boolean blindness:
  prefer named domain enums or an options struct),
- strings represent closed sets, validated IDs, or states that should be
  enums or newtypes,
- a trait object appears only to avoid naming a concrete type,
- boxed trait objects appear even though one concrete type or `impl Trait`
  would work,
- one implementation spawned a deep generic or trait abstraction anyway,
- newtypes exist but immediately expose raw fields everywhere,
- invariant-carrying types expose public fields directly,
- typestate multiplies boilerplate without enforcing a real rule,
- crate features change core semantics rather than optional integration.

Read [generics-vs-dyn.md](references/generics-vs-dyn.md),
[newtypes-and-typestate.md](references/newtypes-and-typestate.md),
[public-api-boundaries.md](references/public-api-boundaries.md), and
[misuse-resistant-apis.md](references/misuse-resistant-apis.md) when one of
those forks becomes the main design pressure. The last covers typestate,
hidden-inner newtypes, anti-boolean-blindness, relevant API Guidelines
tags, and SemVer tooling (`cargo-semver-checks`, `cargo-public-api`).

---
> Source: [leynos/rust-skill](https://github.com/leynos/rust-skill) — distributed by [TomeVault](https://tomevault.io).
<!-- tomevault:4.0:skill_md:2026-06-16 -->

