Reputation: 3604
I am learning typescript and I am facing a problem when I try to define this class in a typescript definition file, and then use it in a typescript file.
I have a javascript "class" which is "Facade" (well known design pattern) of the OpenLayers Library. This facade is like that :
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]));
}
Then, I would like to be able to use this facade in a typescript project. So I wrote my .d.ts file as follow :
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 want to use 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");
});
Everythings compile (oups, tranpile) fine, but when I load my web page containing the script I have the following error :
Uncaught TypeError: Cannot read property 'OpenLayerFacade' of undefined
This occurs when I try to instantiate a new "OpenLayerFacade".
I am using require.js, so I transpile with the option "module": "amd" in my tsconfig.json
My HTML File is :
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<script src="/node_modules/openlayers/dist/ol.js"></script>
<script src="/lib/carto-facade/OpenLayerFacade.js"></script>
<script data-main="/test_ts/cartotester" src="/bower_components/requirejs/require.js"></script>
</head>
<body>
<div id="map" style="width: 75%; height: 400px"></div>
</body>
<input type="number" id="latitude" placeholder="43.5000"><br>
<input type="number" id="longitude" placeholder="5.5000"><br>
</html>
What am I doing wrong ?
I am sure that answer of my question is somewhere on the Typescript Handbook but if someone can help me to find where, I would really appreciate.
Regards,
Upvotes: 0
Views: 3140
Reputation: 950
This code:
import oli = require('../lib/carto-facade/OpenLayerFacade');
means you are importing external module. But your JS code is not external module (you could write such in pure JS if needed). Simple solution should be just omit that line in your TS code. Then you must ensure that JS code creates global variable OpenLayerfacade
(as declared in d.ts) in runtime - you are responsible for loading the JS code. Then in TS use 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");
});
That's how would do it without commonjs - as internal modules aka namespaces.
In case you are using commonjs - and want to use external modules - then your JS code must be commonjs module (external module in terms of TypeScript). Also your declaration file must be wrapped in module to indicate that to compiler.
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 commonjs way:
import oli = require('oli');
You still need
/// <reference path="../lib/carto-facade/OpenLayerFacade.d.ts" />
to tell compiler where to search for 'oli'
module (can be simplified with tsc >1.6).
If your JS snippet is accurate and you don't want or can't change JS to commonjs module you still can mix it in your application using commonjs. Just use first described approach with namespaces.
Upvotes: 1
Reputation: 29884
When using commonjs, an Ambient External Module definition is required. Check this doc: http://www.typescriptlang.org/Handbook#writing-dts-files (§ Ambient External Modules)
There is a way of creating definitions that work for both Internal Modules and External Modules. Something along the lines of (I personnally would have described 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
}
Then import (new 1.6 syntax)
import { OpenLayerfacade } from 'oli'
Upvotes: 1