Reputation: 1
NgbModal's open method takes in a content
parameter typed as any:
// @ng-bootstrap/ng-bootstrap/modal/modal.d.ts
export declare class NgbModal {
open(content: any, options?: NgbModalOptions): NgbModalRef;
}
That returns an NgbModalRef with a function 'get componentInstance()' that also returns any:
// @ng-bootstrap/ng-bootstrap/modal/modal-ref.d.ts
export declare class NgbModalRef {
get componentInstance(): any;
}
I want to create a custom type definition that allows the initial open
function to infer the type of the component instance.
Here's my types.d.ts file:
import {
NgbModal as _NgbModal,
NgbModalOptions,
NgbModalRef as _NgbModalRef
} from '@ng-bootstrap/ng-bootstrap';
declare module '@ng-bootstrap/ng-bootstrap' {
export interface NgbModal extends _NgbModal {
open<T>(content: T, options?: NgbModalOptions): NgbModalRef<T>;
}
export interface NgbModalRef<T> extends _NgbModalRef {
get componentInstance(): InstanceType<T>;
}
}
Here's my modal class:
export type ModalOption = {
title: string;
buttonText: string;
};
@Component({
selector: 'app-modal',
templateUrl: './modal.component.html',
styleUrls: ['./modal.component.scss']
})
export class ModalComponent {
@Input() data: ModalOption = {};
}
Here's where I'm using it:
// Open the modal
const changeConfirmationModal = modalService.open(ModalComponent, {
centered: true
});
// Set the modal data
changeConfirmationModal.componentInstance.data = {
title: 'Some Title',
buttonText: 'Some Button Text'
};
If I don't import and extend the original NgbModal / NgbModalRef in the types.d.ts file, componentInstance.data
is typed correctly, but it breaks my app module as no other exports from @ng-bootstrap
can be found. If I import and extend those two in my types.d.ts file, the inference breaks and componentInstance.data
returns to being typed as any.
Any help would be greatly appreciated.
Upvotes: 0
Views: 89
Reputation: 21
In cases like this, I create my version of the Service, instead of redeclaring the imported Module. Then I can use my type-safe service throughout the application instead of relying directly on the third-party module. See the example below:
type Constructor<T> = new (...args: any[]) => T;
export interface MyModalOptions extends NgbModalOptions {}
export interface MyModalRef<T> extends NgbModalRef {
get componentInstance(): Constructor<T>;
}
@Injectable({
providedIn: 'root'
})
export class MyModalService {
constructor(private ngbModalService: NgbModal) {}
open<T>(content: T, options?: MyModalOptions): MyModalRef<T> {
... opens the modal ...
}
}
this approach creates an interface between the application and the external module where I can modify the modal's service behavior.
Upvotes: 0