Martin Jaskulla
Martin Jaskulla

Reputation: 482

Typescript: A type that allows only objects which implement the same interface

How can I force environment.service to only accept values which implement ServiceInterface?

interface ServiceInterface {
  id: string
}

class ServiceA implements ServiceInterface {
  id = 'a'
}

class ServiceB implements ServiceInterface {
  id = 'b'
}

interface Environment {
  service: ServiceInterface
}

const environment: Environment = {
  service: ServiceA // TS2741: Property 'id' is missing in type 'typeof ServiceA'...
}

I want people to be able to switch out the service in the environment for their own implementation of the service, but only as long as their new implementation adheres to ServiceInterface.

The reason I cannot use an instance service: new ServiceA() is because I am using Angular, where the dependency injection takes care of instantiating the class. I have to supply the class to the dependency injection system. To do that I import my environment file, where I need to make sure that the class added there implements the interface.

Upvotes: 0

Views: 331

Answers (2)

Martin Jaskulla
Martin Jaskulla

Reputation: 482

Found the solutions thanks to this

interface ServiceInterface {
  id: string
}

type Implements<T> = new (...args: any[]) => T;

class ServiceA implements ServiceInterface {
  id = 'a'
}

class ServiceB implements ServiceInterface {
  id = 'b'
}

interface Environment {
  service: Implements<ServiceInterface>
}

const environment: Environment = {
  service: ServiceB
}

Upvotes: 1

bugs
bugs

Reputation: 15323

When you write

const environment: Environment = {
  service: ServiceA
}

the value of the service key is not an instance of the ServiceA class, but the class itself.

You need to pass an actual instance of the class to satisfy the constraint:

const environment: Environment = {
  service: new ServiceA()
}

Upvotes: 2

Related Questions