Syntax Cache
BlogMethodFeaturesHow It WorksBuild a Game
  1. Home
  2. Compare
  3. JavaScript vs TypeScript
  4. JavaScript to TypeScript Interfaces

JavaScript to TypeScript Interfaces

How TypeScript interfaces formalize the implicit object contracts that JavaScript developers maintain through convention and documentation.

Implicit Shapes vs Explicit Interfaces

In JavaScript, object shapes are conventions. A function that expects a "user" object with name and email relies on the caller to pass the right properties. Documentation, tests, and code review enforce the contract. TypeScript interfaces make these contracts explicit: interface User { name: string; email: string }. Declaring an interface does not generate any runtime code -- it is erased during compilation. The payoff is at development time: the compiler checks every object assigned to a User variable, every function receiving a User parameter, and every property access on a User reference. Misspelling email as emial becomes a compile error instead of a silent undefined. For JavaScript migration, interfaces are the second thing most teams add after function parameter types. You start with the most-used shapes (API responses, state objects, configuration), define interfaces for them, and gradually let the type checker catch mismatches. The refactoring burden is low because TypeScript interfaces are structural -- any existing object with the right properties satisfies the interface automatically.

Object shape convention vs interface

JavaScript
/** @param {{ name: string, email: string }} user */
function sendWelcome(user) {
  console.log("Welcome " + user.name);
}
TypeScript
interface User {
  name: string;
  email: string;
}
function sendWelcome(user: User) {
  console.log(`Welcome ${user.name}`);
}
Warm-up1 / 1

Can you write this from memory?

Create Admin interface extending User with role: string

TypeScript: TypeScript Interface vs Type: When to Use Each →

Extending Interfaces

JavaScript creates object hierarchies through prototype chains, class inheritance, or spread composition. TypeScript interfaces extend through the extends keyword: interface Admin extends User { permissions: string[] }. This adds properties from User to Admin without runtime overhead -- no class, no prototype chain, just a type-level inheritance. You can extend multiple interfaces: interface AdminAuthor extends Admin, Author { }. JavaScript has no compile-time equivalent; you would merge objects at runtime and rely on convention to track which properties belong to which "parent." The extends pattern is especially useful for API types. A base response interface (interface ApiResponse { status: number }) can be extended by specific endpoints (interface UserResponse extends ApiResponse { data: User }). This mirrors how JavaScript developers already structure response types, but with compiler enforcement that prevents forgetting required fields. Interface extension and type intersection (Type = A & B) achieve similar results. The difference: interfaces produce clearer error messages (the compiler says "missing property X from interface Y") and support declaration merging, while intersections are more flexible for ad-hoc combinations.

Extending an interface

JavaScript
const admin = {
  ...user,
  permissions: ["read", "write"],
};
// shape is implicit, no validation
TypeScript
interface Admin extends User {
  permissions: string[];
}
const admin: Admin = {
  name: "Ada",
  email: "ada@example.com",
  permissions: ["read", "write"],
};

Multiple extends

JavaScript
const adminAuthor = {
  ...admin,
  ...author,
};
TypeScript
interface Author {
  posts: string[];
}
interface AdminAuthor extends Admin, Author {}
const aa: AdminAuthor = {
  name: "Ada",
  email: "ada@example.com",
  permissions: ["write"],
  posts: ["First post"],
};

Optional Properties and Index Signatures

JavaScript objects can have any combination of properties, and accessing a missing property returns undefined. TypeScript interfaces mark optional properties with ?: interface Config { host: string; port?: number }. The port property becomes number | undefined in the type system, forcing callers to handle the missing case. This is one of the highest-value migrations from JavaScript: marking which fields are guaranteed versus which might be absent prevents an entire class of "Cannot read property of undefined" runtime errors. Index signatures describe objects used as dictionaries: interface StringMap { [key: string]: number }. This tells TypeScript that any string key maps to a number value. JavaScript objects used as maps (const counts = {}; counts["apple"] = 3) are technically record-like, and index signatures formalize that pattern. An index signature combined with named properties creates a hybrid: interface Scores { default: number; [student: string]: number }. The named property must be compatible with the index signature type. JavaScript developers who use objects as lookup tables will find index signatures a natural fit. For more structured key-value needs, TypeScript also supports Map types and the Record<K, V> utility type.

Optional property

JavaScript
function connect(config) {
  const host = config.host;
  const port = config.port || 5432;
}
TypeScript
interface DbConfig {
  host: string;
  port?: number;
}
function connect(config: DbConfig) {
  const host = config.host;
  const port = config.port ?? 5432;
}

Index signature

JavaScript
const scores = {};
scores["Alice"] = 95;
scores["Bob"] = 87;
TypeScript
interface Scores {
  [student: string]: number;
}
const scores: Scores = {};
scores["Alice"] = 95;
scores["Bob"] = 87;

Interface vs Type Alias

TypeScript offers two ways to name object shapes: interface and type. For basic object types, they are interchangeable: interface User { name: string } and type User = { name: string } produce identical behavior. The differences emerge at the edges. Interfaces support declaration merging -- writing interface User twice adds the properties together. This is how TypeScript extends global types (Window, NodeJS.ProcessEnv) and how library authors augment their own types across files. Type aliases do not merge; redeclaring a type alias is an error. On the other hand, type aliases can represent anything: unions (type Result = Success | Failure), tuples (type Pair = [string, number]), primitives (type ID = string), mapped types, and conditional types. Interfaces are limited to object shapes. The community convention has shifted over time. Early TypeScript style guides preferred interfaces for everything, but modern practice leans toward type for most definitions and interface only when you need declaration merging or when defining a public API contract that consumers might extend. Neither choice affects runtime behavior. The decision is about readability, API design, and whether you need merging. For migration, pick one and be consistent within a codebase -- mixing them for equivalent purposes adds cognitive load without benefit.

Equivalent declarations

JavaScript
// JavaScript: no distinction
const user = { name: "Ada", age: 30 };
TypeScript
// Interface
interface User {
  name: string;
  age: number;
}

// Type alias (equivalent for objects)
type User2 = {
  name: string;
  age: number;
};

Declaration merging (interface only)

JavaScript
// not possible in plain JavaScript
TypeScript
interface Window {
  myCustomProp: string;
}
// merges with global Window interface
// window.myCustomProp is now typed
Warm-up1 / 1

Can you write this from memory?

Create Admin interface extending User with role: string

TypeScript: TypeScript Interface vs Type: When to Use Each →

Practice Both Languages

10 free exercises a day. No credit card required. Build syntax muscle memory with spaced repetition.

Free forever. No credit card required.

← Back to JavaScript vs TypeScript
Syntax Cache

Build syntax muscle memory with spaced repetition.

Product

  • Pricing
  • Our Method
  • Daily Practice
  • Design Patterns
  • Interview Prep

Resources

  • Blog
  • Compare
  • Cheat Sheets
  • Vibe Coding
  • Muscle Memory

Languages

  • Python
  • JavaScript
  • TypeScript
  • Rust
  • SQL
  • GDScript

Legal

  • Terms
  • Privacy
  • Contact

© 2026 Syntax Cache

Cancel anytime in 2 clicks. Keep access until the end of your billing period.

No refunds for partial billing periods.