Struggling with generating a TypeScript declaration file

Struggling with creating a typescript definition file for a seemingly 'simple' npm module.

Here are the key points:

Problem: encounter an error when compiling TypeScript:

play.ts(1,9): error TS2305: Module '"/to/the/dir/node_modules/geojson/geojson"' has no exported member 'GeoJSON'.

Module: geojson (https://www.npmjs.com/package/geojson). The package consists of only one public function located in geojson.js:

  (function(GeoJSON) {
  GeoJSON.version = '0.3.0';
  GeoJSON.defaults = {};

  // The sole public function.
  // Converts an array of objects into a GeoJSON feature collection
  GeoJSON.parse = function(objects, params, callback) {
    ...
    ...
    ...
  (typeof module == 'object' ? module.exports : window.GeoJSON = {}));

The package.json contains

"main": "./geojson",
"name": "geojson",
//// I ADDED THIS TYPE DEF FILE
"typings": "./geojson.d.ts",

Based on this information

  1. module name: geojson
  2. parse: signature is parse(objects: any, params: any, callback?: any): any;
  3. Is GeoJSON an interface?

The definition file named geojson.d.ts looks like this:

export declare module geojson {
    interface GeoJSON {
        parse(objects: any, params: any, callback?: any): any;
    }  
}

The tsconfig file appears as follows:

{
    "compilerOptions": {
     "target": "es5",
     "module": "system",
     "moduleResolution": "node",
     "sourceMap": true,
     "emitDecoratorMetadata": true,
     "experimentalDecorators": true,
     "removeComments": false,
     "noImplicitAny": false
    }
}

Attempting to import (tried numerous methods..) including:

import GeoJSON from 'geojson';
import geojson from 'geojson';
import {geojson} from geojson;
import geojson = require('geojson');
import GeoJSON = require('geojson');

Where am I going wrong?

Answer №1

If there are no available typings publicly, you should use the correct type declaration as shown below.

Instead of editing the package.json, consider either using the typings tool to consume typings or saving the type definition below in your source folder as something-or-other.d.ts. Also, remember to add exclude: [ "node_modules" ] to your tsconfig.json to avoid processing anything in the node_modules folder (as it currently processes everything recursively).

The module itself doesn't have a specific namespace or interface. However, keep in mind that within the file, there is a "namespace" (which may be confusing if you're used to .NET/Java, etc.)

declare module 'geojson' {
    export var version : string;
    export var defaults: Object;
    export function parse(data: Object, propreties: Object, callback?: Function) : Object;
}

To use it:

import * as geoJson from 'geojson';

var data = [
        { name: 'Location A', category: 'Store', lat: 39.984, lng: -75.343, street: 'Market' },
        { name: 'Location B', category: 'House', lat: 39.284, lng: -75.833, street: 'Broad' },
        { name: 'Location C', category: 'Office', lat: 39.123, lng: -74.534, street: 'South' }
      ];

var result = geoJson.parse(data, {Point: ['lat', 'lng']});
console.log(result);

This JavaScript code is generated:

"use strict";
var geoJson = require('geojson');
var data = [
    { name: 'Location A', category: 'Store', lat: 39.984, lng: -75.343, street: 'Market' },
    { name: 'Location B', category: 'House', lat: 39.284, lng: -75.833, street: 'Broad' },
    { name: 'Location C', category: 'Office', lat: 39.123, lng: -74.534, street: 'South' }
];
var result = geoJson.parse(data, { Point: ['lat', 'lng'] });
console.log(result);

Output:

c:\code\tmp\geojson>node build\main.js
{ type: 'FeatureCollection',
  features:
   [ { type: 'Feature', geometry: [Object], properties: [Object] },
     { type: 'Feature', geometry: [Object], properties: [Object] },
     { type: 'Feature', geometry: [Object], properties: [Object] } ] }

For more information on typings discovery, check out this blog post:

This is an "ambient" type declaration indicating the existence of a module called geojson with certain members. In your case, the module will be an NPM one located in node_modules.

There are different ways to write typings depending on whether you're working with a local JavaScript file or an npm package. For example, writing an "external" module type declaration involves providing a file name (module.d.ts for module.js) in the same directory. In such cases, the declaration does not include a "declare module" because it is directly tied to the .js file.

Answer №2

It seems that the module definition you have written is not being exported properly, meaning it's not available publicly.

   declare module 'geojson' {
        export interface GeoJSON {
            parse(objects: any, params: any, callback?: any): any;
        }
   }

After fixing this issue, you should be able to use it like this:

import {GeoJSON} from 'geojson';

Have you checked if there are typings available for this library on DefinitelyTyped? EDIT: Paul mentioned in the comments that the only typings available are for the GeoJson schema, not the entire library.

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

When transitioning from Angular5 to Angular6, it seems that the angular.json file has not been properly updated

I am looking to transition from Angular5 to Angular6, following the guidance provided in this answer My attempt to update .angular-cli.json to angular.json using three commands did not yield the expected results: npm install -g @angular/cli npm install @ ...

Guide on extracting the id from the path parameter in an HTTP request using Cloud Functions and nodejs

I am currently in the process of developing a serverless application using GCP Cloud Functions (nodejs). I have successfully implemented different behaviors based on the request method, but I am facing an issue with retrieving the id from the path paramete ...

Arranging JSON array in Angular 6 by specific key within the nested array

Is there a way to sort the data object based on the order numbers inside the array objects? data =[ { name:'' list:{ order :2 }, { name:'' list:{ order :1 } ] ...

What is the best way to transform an array into an object and have it return a specific data

Trying to determine the argument type, but unsure of the next steps function convertArrayToObject(keys) { return keys.reduce((prev, key) => ({ ...prev, [key]: key}), {}) } const output = convertArrayToObject(['aa', 'bb']); // ex ...

Module 'ClientApp/app/app.module' is not located in the directory

Having difficulty importing AppModule into my project and specifying its location. Currently using Visual Studio Code for development. The app.module is situated in project\ClientApp\app, as indicated in this image: https://i.sstatic.net/2jR3X ...

Angular2 with MSAL: Display in a frame denied due to 'X-Frame-Options' set to 'deny'

Hello, I am currently using the code below to log in using AAD B2C. It redirects to the login page and seems to be functioning properly, but when the user ID and password are correct, it redirects back to localhost:4200 without capturing the login detail ...

Best practice for including Angular in the list of dependencies for an npm library

I have developed a small angular package on NPM that I consistently maintain to be compatible with all the latest versions of angular. In my package.json file, I have included angular in the list of peerDependencies to ensure they are always available in p ...

Angular ngFor does not display the JSON response from the API (GET request)

I'm attempting to retrieve a JSON response from my API and display the values on my Angular page using ngFor. Although I don't have any build errors, the values are not being displayed on the page. They only appear in the console when using cons ...

Initiating change notification when utilizing service communication

So I am facing an issue with two unrelated components where I am attempting to establish communication between them using a service and a BehaviorSubject. Despite successfully exchanging data, calling the service from one component does not trigger change ...

In Typescript, how can we reverse the order of an enum

I am encountering a particular challenge with the following code snippet: enum MyEnum { Colors = 'AreColors', Cars = 'AreCars', } const menuTitle = ((obj: MyEnum) => { const newObj = {}; Object.keys(obj). ...

What sets apart a private static function from a public static function in TypeScript?

Exploring the nuances of angular2 services: what distinguishes a private static function from a public static function in typescript? public static getUserStockList(): Stock[] { /* TODO: implement http call */ return WATCHLIST; } vs. priv ...

Troubleshooting: Route guard in Angular 4 not functioning properly on initial page load

While using the canDeactivate guard, I attempted to prevent the browser back action. Interestingly, navigating to the site URL on a new tab successfully brings me to the initial page. However, without any user interaction on the page, pressing the browser ...

Bringing in Static Functions Typescript

Having trouble importing a static class function into my main.js file and encountering an error after compiling with tsc: TypeError: Cannot read property 'router' of undefined at Object. (path/to/main.js:36:27)> Various attempts to assign a ...

"Update your Chart.js to version 3.7.1 to eliminate the vertical scale displaying values on the left

https://i.sstatic.net/7CzRg.png Is there a way to disable the scale with additional marks from 0 to 45000 as shown in the screenshot? I've attempted various solutions, including updating chartjs to the latest version, but I'm specifically intere ...

Adjust the appearance of matSelect when the selection menu is activated

What is the best way to adjust mat-select properties when its options are open? <mat-select class="selector"> <mat-option><mat-option> </mat-select> .selector:focus { color: green; } I attempted using focus, but ...

An error was encountered at line 52 in the book-list component: TypeError - The 'books' properties are undefined. This project was built using Angular

After attempting several methods, I am struggling to display the books in the desired format. My objective is to showcase products within a specific category, such as: http://localhost:4200/books/category/1. Initially, it worked without specifying a catego ...

Is it possible for Typescript interface A to extend B while lacking certain properties from B?

My confusion lies in understanding how TypeScript interfaces function effectively. Here's what I currently have: import type { Socket, Handshake } from 'socket.io'; import type { Session } from './session'; export interface Sessio ...

List the attributes of combined interface declaration

I've come across a challenge when trying to extend the interfaces of third-party libraries globally. Whenever I import other files at the root level, the declaration file loses its global nature. Let me illustrate this with an example: Suppose I wan ...

What could potentially occur if the sourcemap is configured to false within an Angular application?

Recently, I began learning Angular. While exploring my project files, I came across the sourcemap option in the tsconfig.json file, which is set to "sourceMap": true by default. I stumbled upon a helpful link on Stack Overflow that clarified some of my dou ...

Navigating between pages has become challenging due to issues with the navbar, sidebar,

I successfully developed 4 Angular components: 1st component: menu 2nd component: header 3rd component: home 4th component: login The menu component features a sidebar/navbar created using Material UI. The login component consists of the login page. Howe ...