6

I would like to use the latest version of OpenLayers (5.3) in small project. The requirements are:

  • no Node.js - I will be running thing on the site hosted on IIS, simple HTML files
  • scripts need to be written in TypeScript
  • List item
  • ES5

I've read a lot of different discussions and I'm a bit confused. It this even possible? The new OpenLayers has ol npm package, there are (at least two) types definitions for OpenLayers but I can't get it to work in the browser.

First, it complaining about import statements which are not recognized. The other issues are that even if I will include full ol.js I can't get typings to work in TypeScript.

Does anyone have some successful examples?

Fo example bellow the ol namespace is not recognized:

/// <reference path="ol.js"/>
/// <reference path="../Typings/ol/Map.d.ts"/>

// no imports as they are not working without Node.js

class MainMap {

    createMap() {
        var map = new ol.Map({
            target: 'map',
            layers: [
                new ol.layer.Tile({
                    source: new ol.source.OSM()
                })
            ],
            view: new ol.View({
                center: ol.proj.fromLonLat([37.41, 8.82]),
                zoom: 4
            })
        });
    }    
}

let map = new MainMap();
map.createMap();

Anyone is successful with using OpenLayers typings in TypeScript without using Node.js?

2
  • Here is a compiler with docs github.com/niutech/typescript-compile , I don’t see any reason to use ts like that though.
    – dmh126
    Commented Jul 3, 2019 at 7:34
  • 1
    That was not the goal of my question. I know how to compile TypeScript - that is quite obvious that it needs to be compiled. Above code is just an example, my TS scripts will be much bigger so that I see a lot of reasons of using TypeScript (e.g.: because I can use classes). The main problem is that the TS typings are generaed for ol npm package (for for big ol.js) and they are not working in my TS files. Commented Jul 3, 2019 at 8:27

2 Answers 2

0

There are at least 2 type definitions for openlayers. I use both @types/ol and @types/openlayers. The latter has a lot more definitions mapped directly to their corresponding modules in the openlayers library.

In most cases your import statement depends on your compiler/tsconfig options. For instance, you would normally use a statement like import * as <name> from <module>; with typescript, unless you set "esModuleInterop": true in your tsconfig, in which case you can use statements like import <name> from <module>;

You could/should also specify the typeRoots configuration in your tsconfig compiler options. Typically, it would look like this

"typeRoots": [
      "<path to custom types that you might have>",
      "./node_modules/@types/"
    ],

Typescript compiler options

0

https://github.com/ca0v/react-lab is an example of a project that uses Typescript and OpenLayers and React without Webpack and without OpenLayers typings. It imports the OpenLayers source directly. It does require using an AMD module loader. See https://github.com/ca0v/react-lab/blob/master/tsconfig.json for details:

{
  "compilerOptions": {
    "baseUrl": "./",
    "allowJs": true,
    "target": "es2020", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
    "module": "amd", /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    "jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    "jsxFactory": "create",
    "sourceMap": true,
    "inlineSources": true,
    "inlineSourceMap": false,
    "outFile": "./built/index.js",
    "strict": false,
    "paths": {
      "@ol/*": [
        "./node_modules/ol/src/*"
      ],      
      "rbush/rbush.js":["./node_modules/rbush/index.js"],
      "quickselect":["./node_modules/quickselect/index.js"],
      "pbf": [
        "./pbf.js"
      ],      
      "ieee754": [
        "./ieee754.js"
      ],
    }
  },
  "files": ["./index.tsx"],
  "exclude": [
    "./built/*"
  ],
}

Here is my package.json at the time of this writing, where some modules are not yet ported to EJS:

{
  "name": "react-lab",
  "version": "1.0.0",
  "description": "Typescript + TSX + React + RequireJS",
  "main": "index.js",
  "scripts": {
    "watch": "tsc -w"
  },
  "author": "",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/ca0v/react-lab.git"
  },
  "bugs": {
    "url": "https://github.com/ca0v/react-lab/issues"
  },
  "homepage": "https://github.com/ca0v/react-lab#readme",
  "devDependencies": {
    "@types/material-ui": "^0.20.0",
    "@types/react": "^16.0.25",
    "@types/react-dom": "^16.0.3",
    "live-server": "^1.2.1",
    "ol": "^6.4.3",
    "simplify-geojson": "^1.0.3",
    "terser": "^5.0.0",
    "typescript": "^3.9.7"
  }
}

I was luck enough to find rbush/index.js, which is an javascript module. I load that instead of rbush.js using the "paths" option. I did the same for quickselect. I was not so luck with pbf and ieee754, both of which use a non-compatible module syntax. It was trivial to port them.

Now I can produce a index.js and index.js.map containing all the parts of openlayers that I imported and nothing more and thanks to the ol developers the modules I do import are strongly typed, even though they are js files. Here is a snippet from https://github.com/ca0v/react-lab/blob/master/components/openlayers.tsx:

import Map from "@ol/Map";
import VectorSource from "@ol/source/Vector";
import VectorLayer from "@ol/layer/Vector";
import Geometry from '@ol/geom/Geometry';
import type GeometryType from '@ol/geom/GeometryType';
import { GeoJSON } from '@ol/format';
import View from '@ol/View';
import { fromLonLat } from "@ol/proj";
import * as interaction from "@ol/interaction";
import type MapBrowserEvent from '@ol/MapBrowserEvent';
import Feature from '@ol/Feature';
import type Collection from '@ol/Collection';
import type { Coordinate } from '@ol/coordinate';
import BingMaps from "@ol/source/BingMaps";
import XYZ from "@ol/source/XYZ";
import OSM from "@ol/source/OSM";
import TileLayer from "@ol/layer/Tile";
import TileSource from '@ol/source/Tile';
import { Extent, getCenter } from '@ol/extent';
import Zoom from "@ol/control/Zoom";
import ZoomSlider from "@ol/control/ZoomSlider";
import FullScreen from "@ol/control/FullScreen";
import MousePosition from "@ol/control/MousePosition";
import Rotate from "@ol/control/Rotate";
import ScaleLine from "@ol/control/ScaleLine";
import ZoomToExtent from "@ol/control/ZoomToExtent";

const ol = {
    interaction,
    control: 
    {
        ScaleLine,
        Rotate,
        MousePosition,
        FullScreen,
        Zoom,
        ZoomSlider,
        ZoomToExtent,
    },
    source: {
        XYZ,
        OSM,
        Vector: VectorSource
    },
    layer: {
        Vector: VectorLayer
    }
};

It is important to realize I am not using openlayers typings but actually importing the openlayers source code. If you setup tsc in watch mode re-compiles are pretty quick. it is also important to realize I am not using webpack or rollup to do this. This is pure typescript transpiling.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.