catchall
catchall

Reputation: 21

Storing type as a dictionary key

I'm trying to create a mapping GenericInterface -> ConcreteFactory<GenericInterface> in typescript. And it works as long as GenericInterace has no methods or properties. But if I'm adding something to this interface, than this error occurs: Property 'XXX' is missing in type 'typeof ClassThatImplementsGenericInterface' but required in type 'GenericInterface'.

I assume that this happens because getOrCreate expects instance and not a type, but i don't understand how I can implement such behaviour in typescript without using strings (component names) as dictionary keys.

// how factories are stored
private _factories: Dictionary<IComponent, Factory<IComponent>>;

// creates and returns factory for component
public getOrCreate<T extends IComponent>(component: IComponent): Factory<T> {
   if (this._factories.has(component)) {
      return this._factories.get(component) as Factory<T>;
   }

   let factory = new Factory<T>();

   this._factories.set(component, factory);

   return factory as Factory<T>;
}

// without XXX everything works
interface IComponent {
    XXX(): string;
}

// this is where error occurs
factories.getOrCreate(TestComponent);

Upvotes: 0

Views: 84

Answers (1)

Michael Antipin
Michael Antipin

Reputation: 3532

The Dictionary<IComponent bit literally says, that your key is IComponent. However, this is not what you are trying to do: the key should rather be something that creates IComponent.

Take a look at how the official documentation describes using constructors in interfaces.

Let's create another interface for that:

interface IComponentCtor {
    new (): IComponent;
}

This describes something that creates IComponent (add constructor parameters as needed).

class TestComponent implements IComponent {
    constructor() {} // complies with IComponentCtor
}

And the signature of getOrCreate is now

public getOrCreate(component: IComponentCtor): Factory<IComponent>

Now you can use TestComponent as a key of your dictionary as IComponentCtor: Dictionary<IComponentCtor, Factory<IComponent>>.

Upvotes: 2

Related Questions