0

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.

1
  • const environment: Environment = { service: { id: 'a' } } Commented Mar 19, 2020 at 11:41

2 Answers 2

2

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()
}
Sign up to request clarification or add additional context in comments.

2 Comments

I understand, thanks. Is there a way around this though? Maybe a custom type to achieve what I want instead?
Custom type is only compile time. You need to have value. When you do new X you get instance value.
1

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
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.