Search code examples
angulartypescriptjasmine

Resolving template parameters of a function that's taken from the interface


I have an issue with resolving types, can't wrap my head around it.

I have a ModalService with a function with such signature:

openModal<
   T extends ModalResult = DocumentModalResult, 
   W extends ModalData = DocumentModalData>
(type: ModalType, data: W): Observable<T>

There is a component that uses that service:

// interface IExampleData = { someProperty: number }

onConfirm(): void {
   // do stuff
   this.modalService.openModal<IExampleResult, IExampleData>(type, data);
}

Now I'm trying to write tests for it:

const modalService = getService(ModalService); // returns instance of ModalService

const openModalSpy = spyOn(modalService, 'openModal');

// do some stuff 

expect(openModalSpy).toHaveBeenCalledWith(ModalType.Example, { someProperty: 1 });

And obviously types don't match: 'someProperty' does not exist in type DocumentModalData

How can I modify the "openModalSpy" type to have it resolved by Typescript?

I do realize that I should write something like this with overriding function's generic parameters, but I don't know how.

const openModalSpy: jasmine.Spy<ModalService['openModal']> = spyOn(modalService, 'openModal');


Solution

  • I would use the as any type cast:

    expect(openModalSpy).toHaveBeenCalledWith(ModalType.Example, { someProperty: 1 } as any);
    

    Sometimes getting the TypeScript right with Jasmine either can't be done or takes a long time/effort to figure out.