Tools

TypeScript Interface Generator

Generate complete TypeScript interfaces with primitive types, nested objects, arrays, and optionals. Ready to copy into your project with consistent naming and correct types.

Instant🔒In your browserNo signup
Live
    View as text

    Structure of a TypeScript interface

    An interface defines the shape of an object: what properties it has and what types they are. Basic syntax: interface User { id: number; name: string; email: string; }. Each property has a name, colon, and its type. Primitive types are string, number, boolean, null, undefined.

    Optional properties are marked with ?: avatar?: string means it may or may not exist. Readonly properties are immutable: readonly id: number can't be reassigned after creation. Arrays are typed with string[] or Array<string>, both valid.

    For nested objects, you can define interfaces inline or reference other interfaces: address: { street: string; city: string } or address: Address where Address is another interface. The second option is preferable for reusability. Union types combine options: status: 'active' | 'inactive' | 'pending'.

    Naming conventions and organization

    Interface names use PascalCase: UserProfile, ApiResponse, ProductDetails. Avoid redundant prefixes like IUser (C# inheritance, unnecessary in TS). If you have name conflicts, use descriptive suffixes: UserEntity vs UserDto vs UserViewModel.

    Organize interfaces by feature or layer. In a React project: components/Button/Button.types.ts for props, api/users/types.ts for responses. Don't throw everything in a global types.ts; that file grows out of control and nobody knows who's using what. Exception: globally shared types go in @types or shared/types.

    For types from external APIs, consider autogenerating with tools like openapi-typescript or quicktype. Writing 200 lines of interface by hand for a Stripe response is guaranteed human error. If the API has OpenAPI/Swagger schema, generate it; if not, ask them to add it.

    Utility types and composition

    TypeScript includes utility types that transform existing interfaces. Partial<User> makes all props optional (useful for updates). Required<User> does the opposite. Pick<User, 'id' | 'name'> selects only those props. Omit<User, 'password'> excludes the password prop.

    Record<string, number> is an object with string keys and number values, useful for dynamic mappings. Readonly<User> makes the entire interface immutable. NonNullable<T> removes null/undefined from a type. These utilities avoid duplication: you don't need a separate UserUpdate if you can use Partial<User>.

    For composition, extend interfaces: interface Admin extends User { permissions: string[] }. Or use intersection: type AdminUser = User & { permissions: string[] }. The difference: extends is for interfaces (can be redeclared), & is for types (more flexible but not redeclarable).

    Common mistakes and how to avoid them

    Mistake #1: using any out of laziness. data: any destroys TypeScript's purpose. If you don't know the exact type, use unknown and do type narrowing with guards. Or define the interface partially and iterate: better to have 3 typed props than everything in any.

    Mistake #2: overly generic interfaces. interface Data { value: any } adds nothing. Be specific: interface UserData { userId: string; loginCount: number }. The more concrete the type, the more errors the compiler catches.

    Mistake #3: not typing API responses. Fetch returns any by default. Always type: const user = await fetch('/api/user').then(r => r.json()) as User or better, use a typed client like tRPC, GraphQL Codegen, or axios with interceptors that typecheck.

    Mistake #4: duplicating definitions. If User in frontend and backend are identical, share the type (monorepo with shared package, or export from backend if it's TypeScript too). Keeping two definitions manually synced is a recipe for subtle bugs where a field changed type and frontend didn't find out.

    FAQ

    When do I use interface vs type?

    For objects, prefer interface (more readable and can extend/redeclare). For unions, complex intersections, or primitives, use type. In practice, it's mostly team preference.

    Should I type absolutely everything?

    Every public function, every component prop, every API response. Internal helper functions can be inferred if the type is obvious. The goal is to detect errors at boundaries (module input/output).

    How do I type an object with dynamic keys?

    Use index signature: <code>interface Config { [key: string]: string | number }</code> or Record: <code>Record&lt;string, string | number&gt;</code>. Both say 'any string key can have these types of values'.

    What do I do with third-party data without types?

    Search in DefinitelyTyped (@types/library). If it doesn't exist, define your own types in a local .d.ts. Don't let lack of external types infect your codebase with anys.

    Was this generator useful?