Function Types

Interfaces are capable of describing the wide range of shapes that JavaScript objects can take. In addition to describing an object with properties, interfaces are also capable of describing function types.
To describe a function type with an interface, we give the interface a call signature. This is like a function declaration with only the parameter list and return type given. Each parameter in the parameter list requires both name and type.
type HttpRequest = ( url: string, options: Record<string, any> ) => Promise<any>; const request: HttpRequest = ( url, options = {} ) => { return Promise.resolve( { url, options } ); } // Property 'get' does not exist on type 'HttpRequest' request.get = function() { }

call signature

// call signature type Fn = { ( name: string ): string; } const fn: Fn = ( name: string ): string => { return name; }
interface HttpRequest { get: ( ...args: any[] ) => any; ( url: string, options: Record<string, any> ): Promise<any>; } const request: HttpRequest = ( url, options = {} ) => { return Promise.resolve( { url, options } ); } request.get = function() { }
type HttpRequest = ( url: string, options: Record<string, any> ) => Promise<any>; <HttpRequest>function request( url, options = {} ) { return Promise.resolve( { url, options } ); } export namespace request { export function get() {} }

Class Types

Difference between the static and instance sides of classes.

When working with classes and interfaces, it helps to keep in mind that a class has two types: the type of the static side and the type of the instance side. You may notice that if you create an interface with a construct signature and try to create a class that implements this interface you get an error.
This is because when a class implements an interface, only the instance side of the class is checked. Since the constructor sits in the static side, it is not included in this check.

Constructor Types

type Sex = 'male' | 'female'; interface Person { age: number; growup( n: number ): Person; } interface PersonConstructor { new ( name: string, sex: Sex ): Person; } // Type 'typeof Male' is not assignable to type 'PersonConstructor'. // Types of parameters 'sex' and 'sex' are incompatible. // Type 'string' is not assignable to type 'number'. // Type 'string' is not assignable to type 'number'.(2322) const Male: PersonConstructor = class implements Person { age: number = 30; constructor( public name: string, public sex: number ) { } growup( n: number ): this { this.age += n; return this; } } // Argument of type '"unknown"' is not assignable to parameter of type 'Sex'.(2345) new Male( 'Achilles', 'unknown' );
 

Interfaces Extending Classes

When an interface type extends a class type it inherits the members of the class but not their implementations. It is as if the interface had declared all of the members of the class without providing an implementation. Interfaces inherit even the private and protected members of a base class. This means that when you create an interface that extends a class with private or protected members, that interface type can only be implemented by the class or a subclass of it.
This is useful when you have a large inheritance hierarchy, but want to specify that your code works with only subclasses that have certain properties. The subclasses don't have to be related besides inheriting from the base class.

Types and Interfaces

// Try it out on TypeScript Playground function get( key: string, obj: Record<string, string> ): string { return obj[ key ]; } interface A { name: string; } const a: A = { name : 'Achilles' }; // Argument of type 'A' is not assignable to parameter of type 'Record<string, string>'. // Index signature is missing in type 'A'.(2345) get( 'name', a ); type B = { name: string; } const b: B = { name : 'Achilles' }; get( 'name', b );
// Try it out on TypeScript Playground // First case (expected) type A = { [ x: string ]: number }; type B = { x: number }; const b: B = { x : 1 }; const a: A = b; // no error // Second case (unexpected) interface C { [ x:string ]: number } interface D { x: number } const d: D = { x : 1 }; // Type 'D' is not assignable to type 'C'. // Index signature is missing in type 'D'.(2322) const c: C = d; // Third case (expected) interface E { [ x: string ]: number } interface F extends E { x: number } const f: F = { x : 1 }; const e: E = f; // no error // Fourth case (expected) interface G { [ x: string ]: number } type H = { x: number }; const h: H = { x : 1 }; const g: G = h; // no error // Fifth case (maybe expected?) type I = { [ x: string ]: number } interface J { x: number } const j: J = { x : 1 }; // Type 'J' is not assignable to type 'I'. // Index signature is missing in type 'J'.(2322) const i: I = j;
 
badge