Versions
npm: 3.10.9
systemjs: 0.19.41
typescript: 1.8.10
rxjs: 5.0.3
Background
I have a project (that's written in typescript) that i'm trying to add rxjs
to, but have come across an issue when loading the bundled file through systemjs
.
SystemJs config
System.config({
transpiler: 'typescript',
paths: {
'src:*': '/src/*',
'npm:*': '/node_modules/*'
},
map: {
'lib': 'src:lib',
'rxjs': 'npm:rxjs/bundles/Rx.js',
'typescript': 'npm:typescript/lib/typescript.js',
'systemjs': 'npm:systemjs/dist/system.src.js'
},
packages: {
lib: {
defaultExtension: 'js'
}
}
});
Problem
Using the above config, i get the following error.
Error: (SystemJS) undefined is not a constructor (evaluating '__extends(UnsubscriptionError, _super)')
Which is caused by the fact that systemjs incorrectly defaults to amd
format and the exporter
function on line 245 of Rx.js
never gets executed.
From the systemjs docs:
Module format detection
When the module format is not set, automatic regular-expression-based detection is used. This module format detection is never completely accurate, but caters well for the majority use cases.
Attempted solution
I presumed that explicitly setting the rxjs
package format to global
in the config would fix this issue.
System.config({
transpiler: 'typescript',
paths: {
'src:*': '/src/*',
'npm:*': '/node_modules/*'
},
map: {
'lib': 'src:lib',
'rxjs': 'npm:rxjs/bundles/Rx.js',
'typescript': 'npm:typescript/lib/typescript.js',
'systemjs': 'npm:systemjs/dist/system.src.js'
},
packages: {
lib: {
defaultExtension: 'js'
},
rxjs: {
format: 'global'
}
}
});
Problem 2
Although this fixed the first issue, it created a second. As everywhere that i attempt to use the rxjs
imports now throws an error, as they're undefined
.
import {Observable} from 'rxjs'
export class SomeClass {
...
private _isObservable(arg: any): boolean {
return arg instanceof Observable;
}
}
Uncaught TypeError: Right-hand side of 'instanceof' is not an object at SomeClass._isObservable
Debugging the transpiled code in the console reveals that although window.Rx
gets correctly set to the Rx
object, the rxjs_1_1
object that gets set on SomeClass
, is not the global Rx
object, but instead another object with the Rx
global set as a property 'Rx' on it.
So rxjs_1.Rx.Observable
works, but not of rxjs_1.Observable`.
(function(System, SystemJS) {System.register(['rxjs'], function(exports_1, context_1) {
"use strict";
var __moduleName = context_1 && context_1.id;
var rxjs_1;
var SomeClass;
return {
setters:[
function (rxjs_1_1) {
rxjs_1 = rxjs_1_1;
}],
execute: function() {
SomeClass = (function () {
function SomeClass() {
}
...
SomeClass.prototype._isObservable = function (arg) {
return arg instanceof rxjs_1.Observable;
};
return SomeClass;
}());
exports_1("SomeClass", SomeClass);
}
}
});
Question
Any idea how i get it to pass in Rx
object instead?
By adding 'Rx'
as the meta.rxjs.exports
value in system.config
, it allows you to select the Rx
object to be imported, instead of its parent. You can use dot notation to select an even deeper object if necessary.
Not that you would want to, but just as an example, exports: 'Rx.Observable'
would set the property rxjs_1_1
to Observable
in my original questions transpiled code.
So the full system.config
would be:
System.config({
transpiler: 'typescript',
paths: {
'src:*': '/src/*',
'npm:*': '/node_modules/*'
},
map: {
'lib': 'src:lib',
'rxjs': 'npm:rxjs/bundles/Rx.js',
'typescript': 'npm:typescript/lib/typescript.js',
'systemjs': 'npm:systemjs/dist/system.src.js'
},
packages: {
lib: {
defaultExtension: 'js'
}
},
meta: {
rxjs: {
format: 'global',
exports: 'Rx'
}
}
});