Unable to employ a custom Typescript .d.ts file

Currently, I am delving into learning TypeScript and encountering a hurdle while attempting to define a class in a TypeScript definition file and then utilize it in a TypeScript file.

The dilemma lies with a JavaScript "class" called "Facade," which serves as a well-known design pattern of the OpenLayers Library. The structure of this facade looks like this:

lib/carto-facade/OpenLayerFacade.js :

function OpenLayerFacade() {
    this.map =   new ol.Map({
        layers: [
            new ol.layer.Tile({source: new ol.source.OSM()})
        ],
        view: new ol.View({
            center: [43.5, 5.0],
            zoom: 2
        }),
        target: 'map'
    });
}

OpenLayerFacade.prototype.setViewCenter = function(latitude, longitude)  {
    this.map.getView().setCenter(ol.proj.fromLonLat([longitude, latitude]));
}

Subsequently, I wish to employ this facade in a TypeScript project. Consequently, I formulated my .d.ts file as follows:

lib/carto-facade/OpenLayerFacade.d.ts

declare interface OpenLayerfacade {
    setViewCenter(latitude:number, longitude:number):void;
}

declare interface OpenLayerfacadeFactory {
    new(divName:string): OpenLayerfacade;
}

export var OpenLayerfacade:OpenLayerfacadeFactory;

Now, I aim to utilize it in a TS script loaded by a browser:

/// <reference path="../typings/jquery/jquery.d.ts" />
/// <reference path="../lib/carto-facade/OpenLayerFacade.d.ts" />

import oli = require('../lib/carto-facade/OpenLayerFacade');

$(document).ready(function () {
    var ol = new oli.OpenLayerFacade("map");
    ol.setViewCenter(43.5, 6.0);
    console.log("Map displayed");
});

While everything compiles (transpiles) successfully, upon loading my webpage containing the script, I encounter the following error:

Uncaught TypeError: Cannot read property 'OpenLayerFacade' of undefined

This issue arises when I attempt to instantiate a new "OpenLayerFacade".

I have been using require.js, therefore transpile with the option "module": "amd" in my tsconfig.json

The structure of my HTML File is as shown below:

<html lang="en">
...

What could be going wrong?

I believe that the solution to my predicament might lie within the TypeScript Handbook. Any guidance on locating the relevant information would be greatly appreciated.

Kind regards,

Answer №1

When utilizing commonjs, it is essential to have an Ambient External Module definition in place. For detailed information, refer to this documentation: http://www.typescriptlang.org/Handbook#writing-dts-files (§ Ambient External Modules)

To cater to both Internal Modules and External Modules, there exists a method for creating definitions that serve dual purposes. One example could involve defining a class.

//Internal module
declare namespace Oli {
    class OpenLayerfacade {
        constructor(divName:string);
        setViewCenter(latitude:number, longitude:number):void;
    }
}

//External module
declare module "oli" {
    export = Oli
}

Subsequently, import using the new 1.6 syntax

import { OpenLayerfacade } from 'oli'

Answer №2

Here's what the code is doing:

import oli = require('../lib/carto-facade/OpenLayerFacade');

This line means that you are bringing in an external module. However, your JavaScript code is not an external module (you could write it in pure JS if necessary). A simple solution would be to remove that line from your TypeScript code. Instead, make sure that your JS code creates a global variable OpenLayerfacade (as specified in d.ts) during runtime - it's up to you to load the JS code. Then in TypeScript, use the declared global variable.

/// <reference path="../typings/jquery/jquery.d.ts" />
/// <reference path="../lib/carto-facade/OpenLayerFacade.d.ts" />

$(document).ready(function () {
    var ol = new OpenLayerFacade("map");
    ol.setViewCenter(43.5, 6.0);
    console.log("Map displayed");
});

This is how you would handle it without using commonjs - by using internal modules or namespaces.

If you are using commonjs and want to utilize external modules, then your JS code should be a commonjs module (an external module in TypeScript terminology). Additionally, wrap your declaration file in a module to inform the compiler about it.

export modules 'oli' {
    declare interface OpenLayerfacade {
        setViewCenter(latitude:number, longitude:number):void;
    }

    declare interface OpenLayerfacadeFactory {
         new(divName:string): OpenLayerfacade;
     }

    export var OpenLayerfacade:OpenLayerfacadeFactory;
}

and import it in a commonjs manner:

import oli = require('oli');

You still need

/// <reference path="../lib/carto-facade/OpenLayerFacade.d.ts" />

to specify to the compiler where to find the 'oli' module (this can be simplified with tsc >1.6).

If your JS snippet is correct and you don't want or can't convert JS to a commonjs module, you can still integrate it into your application using commonjs. Simply follow the first method described with namespaces.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide on creating a Typescript function with a strongly typed argument

I am looking to develop a function that accepts a type created using export class and imported in the traditional manner as an extension of a particular type. With a base Page class and various derived classes, I aim to have this function capable of receiv ...

Error: AppModule requires an array of arguments in order to function properly

Upon successfully compiling my Angular application and running ng serve, I encountered the following error in the browser console. AppComponent_Host.ngfactory.js? [sm]:1 ERROR Error: Arguments array must have arguments. at injectArgs (core.js:1412) at c ...

typegrapql encounters an issue with experimentalDecorators

I'm currently delving into TypeGraphQL and working on building a basic resolver. My code snippet is as follows: @Resolver() class HelloReslover { @Query(() => String) async hello(){ return "hello wtold" } } However, ...

Using Mat-Error for Two Way Binding leads to frequent triggering of ngModelChange事件

I am working with a mat input field that has two-way data binding using ngModel, and I want to add validation using mat-error and formControl. <mat-form-field [formGroup]="myForm"> <input matInput formControlName="myFormName" autocomplete="off" ...

No matter what I attempt, Ng-options is still failing to work properly

This is my custom selection element: <select ng-options="country.country for country in countries" formControlName="country"></select></label> Below is the TypeScript component code associated with it: import { Component } from ' ...

An error occurs when attempting to access a property that does not exist on type 'never'. Why is this considered an error rather than a warning?

I am experiencing an issue with the following code snippet: let count: number | undefined | null = 10; count = null; let result: string | undefined | null = count?.toFixed(2); console.log(`Result: ${result}`); The error message I received is as follows: ...

Tips for integrating the react-financial-charts library into your React and JavaScript project

While exploring the react-financial-charts library, I discovered that it is written in TypeScript (TS). Despite my lack of expertise in TypeScript, I am interested in using this library in my React+JS project due to its active contributions. However, I hav ...

What is the best method for retrieving an item from localstorage?

Seeking advice on how to retrieve an item from local storage in next.js without causing a page rerender. Here is the code snippet I am currently using: import { ThemeProvider } from "@material-ui/core"; import { FC, useEffect, useState } from "react"; i ...

What is the best way to implement a switch case with multiple payload types as parameters?

I am faced with the following scenario: public async handle( handler: WorkflowHandlerOption, payload: <how_to_type_it?>, ): Promise<StepResponseInterface> { switch (handler) { case WorkflowHandlerOption.JOB_APPLICATION_ACT ...

Turn off TypeScript's type validation during production builds

For my petite project, I am utilizing Next.js with TypeScript. A thought has been lingering in my mind lately: is there a way to turn off the types validity checks while executing npm run build? Since the type checking occurs during npm run dev, it seems ...

The error message from ANGULAR states that it cannot locate the control with the specified path: 'childrenFormArray -> [object Object] -> gender'

I'm currently working on an angular project and facing a challenge in adding multiple children with their age and gender dynamically using reactive forms. Although I can add the form, I am having trouble with the delete functionality as it keeps throw ...

How to Toggle Visibility of Angular2 Material Drop Down Menu?

My Code <mat-form-field class="button-spacing"> <mat-select placeholder="select" [(ngModel)]="dropDownOne"> <mat-option *ngFor="let first of test1" [value]="first"> {{ first }} </mat-option> </mat-select> </mat-fo ...

Struggling with integrating Axios with Vue3

Can someone assist me in figuring out what is going wrong with my Axios and Vue3 implementation? The code I have makes an external call to retrieve the host IP Address of the machine it's running on... <template> <div id="app"> ...

Encountering a TS1005 error while trying to import types from a type definition file

Within my project, one of the libraries called parse5 is providing typing information in .d.ts files. The current syntax used to import types is causing several TypeScript errors during application runtime because TypeScript does not seem to recognize this ...

Determine the date and time based on the number of days passed

Hey there! I have a dataset structured like this: let events = { "KOTH Airship": ["EVERY 19:00"], "KOTH Castle": ["EVERY 20:00"], Totem: ["EVERY 17:00", "EVERY 23:00"], Jum ...

Angular: Initiate multiple functions simultaneously and combine results afterwards

My current code successfully zips and saves the response of a JSON array by splitting them into individual files using a single method. zip: JSZip = new JSZip(); folder: JSZip = new JSZip(); this.apicall.api1() .subscribe( response => { for (let r ...

The type declaration for the Storage.prototype.setObject method

I'm facing a challenge in creating a d.ts file for the given DOM feature. Storage.prototype.setObject = function(key:string, value:any) { this.setItem(key, JSON.stringify(value)); } Storage.prototype.getObject = function(key:string) { var va ...

I encounter an error message stating "Cannot read property 'push' of undefined" when trying to add an item to a property within an interface

I have a model defined like this : export interface AddAlbumeModel { name: string; gener: string; signer: string; albumeProfile:any; albumPoster:any; tracks:TrackMode[]; } export interface TrackMode { trackNumber: number; ...

Exploring Angular 2 with Visual Studio 2015 Update 1 in the context of Type Script Configuration

After spending the last week attempting to set up and launch a simple project, I am using the following configuration: Angular 2, Visual Studio 2015 update 1, TypeScript Configuration In the root of my project, I have a tsconfig.Json file with the follow ...

What steps should I take to ensure that TypeScript acknowledges the validity of my object assignment?

Trying to implement this code: type A = { b: false, } | { b: true, p: string; } function createA(b: boolean, p: string | undefined): A { if (b && p === undefined) { throw 'Error'; } const a: A = { b, ...