Trying to create a mock for uirouter's StateService has been a bit challenging for me. This is what I have attempted:
beforeEach(() => {
stateService = jasmine.createSpyObj('StateService', ['go']) as StateService;
}
...
it('calls go', () => {
// ...
let options = { location: 'replace', inherit: true };
expect(stateService.go).toHaveBeenCalledWith('foo', params, options);
});
The error message I receive is:
error TS2345: Argument of type '{ location: string; inherit: boolean; }' is not assignable to parameter of type 'Expected'. Type '{ location: string; inherit: boolean; }' is not assignable to type '{ location?: ExpectedRecursive<boolean | "replace">; relative?: ExpectedRecursive<string | StateObject | StateDeclaration>; ... 8 more ...; source?: ExpectedRecursive<...>; }'. Types of property 'location' are incompatible. Type 'string' is not assignable to type 'ExpectedRecursive<boolean | "replace">'. expect(stateService.go).toHaveBeenCalledWith('foo', params, options);
However, if I place the object directly without assigning it to a variable, everything works smoothly:
it('calls go', () => {
// ...
expect(stateService.go).toHaveBeenCalledWith('foo', params, { location: 'replace', inherit: true });
});
I noticed that uirouter's TransitionOptions interface allows for optional properties:
export interface TransitionOptions {
location?: boolean | 'replace';
relative?: string | StateDeclaration | StateObject;
inherit?: boolean;
notify?: boolean;
reload?: boolean | string | StateDeclaration | StateObject;
custom?: any;
supercede?: boolean;
reloadState?: StateObject;
redirectedFrom?: Transition;
current?: () => Transition;
source?: 'sref' | 'url' | 'redirect' | 'otherwise' | 'unknown';
}
Even though everything is optional in the interface, Typescript seems to have an issue when I assign this interface to a simple object as a variable. Why does Typescript behave like this?