Skip to main content

Interface

interface Name {
first: string
second: string
}

let name: Name
name = {
first: 'John',
second: 'Doe',
}

name = {
// Error: 'Second is missing'
first: 'John',
}

name = {
// Error: 'Second is the wrong type'
first: 'John',
second: 1337,
}

Interface Function

  • Use a method function for class instances (this binding to function).
  • Use a property function otherwise.
interface HasBothFunctionTypes {
method: () => string
property: () => string
}

Interface Implementation

Implementing interface is purely safety check, does not copy any interface members onto class definition:

interface Crazy {
new (): {
hello: number
}
}

class CrazyClass implements Crazy {
constructor() {
return { hello: 123 }
}
}

// Because
const crazy = new CrazyClass() // crazy would be { hello:123 }

Interface Extension

Overridden Properties

Overridden property must be assignable to its base property (ensure derived interface assignable to base interface):

interface WithNullableName {
name: string | null
}

interface WithNonNullableName extends WithNullableName {
name: string
}

interface WithNumericName extends WithNullableName {
name: number | string
}
// Error: Interface 'WithNumericName' incorrectly
// extends interface 'WithNullableName'.
// Types of property 'name' are incompatible.
// Type 'string | number' is not assignable to type 'string | null'.
// Type 'number' is not assignable to type 'string'.

Interface Merging

Interface merging isn’t used often in day-to-day TypeScript development, but useful for augmenting interfaces from external 3rd-party packages (e.g. Cypress) or built-in global interfaces (e.g. Window):

// Lib a.d.ts
interface Point {
x: number
y: number
}
declare const myPoint: Point

// Lib b.d.ts
interface Point {
z: number
}

// Your code
const z = myPoint.z // Allowed!

Extend 3rd-party module interface:

declare module '3rd-party-module' {
export interface Interface {
foo: { title: string }
}
}

Interface and Type Alias

  • Type aliases may not participate in declaration merging, but interfaces can.
  • Interfaces may only be used to declare the shapes of object, not re-name primitives.
  • The key distinction is that a type cannot be re-opened to add new properties, an interface which is always extendable.
interface Window {
title: string
}

interface Window {
ts: TypeScriptAPI
}

const src = 'const a = "Hello World"'
window.ts.transpileModule(src, {})