How to use Aurelia third party plugin with without typescript definition file? - plugins

I am new to Aurelia and Typescript. I am trying to use a the aurelia-dialog plugin inside of my project. I have follow all the necessary steps and am getting an error "cannot find module "aurelia-dialog". The offending line is
import {DialogService, DialogController} from "aurelia-dialog";
I am pretty sure all of the config is set up correctly because this is my only error. I have
aurelia.use
.standardConfiguration()
.developmentLogging()
.plugin('aurelia-dialog');
Do I need to create a typescript definition file for this to work, if so how? Or am I missing something and this should work as-is?

Looks like the aurelia-dialog build hasn't been configured to produce TypeScript definition files yet. This will probably be added soon. In the meantime you could add an aurelia-dialog.d.ts file to your project with the following:
declare module 'aurelia-dialog' {
export class DialogService {
open(settings: any): Promise;
}
export class DialogController {
constructor(renderer, settings, resolve, reject);
ok(result: any): Promise<DialogResult>;
cancel(result: any): Promise<DialogResult>;
error(message): Promise<DialogResult>;
close(ok: boolean, result: any): Promise<DialogResult>;
settings: {lock: boolean, centerHorizontalOnly: boolean };
}
export class DialogResult {
wasCancelled: boolean;
output: any;
constructor(cancelled: boolean, result: any);
}
}

Related

Can't make webpack ProvidePlugin work

I have file where I export object
let myHelper = {
hello() {
console.log('hello')
}
}
export default myHelper;
In webpack I could set alias, and this work for e.g. import myHelper from 'myHelper':
alias: {
myHelper: path.resolve(__dirname, 'app/folder/myHelper.js')
}
But I can't require it properly in ProvidePlugin. I've tried many possible combinations from other answers...
myHelper: path.resolve(__dirname, 'app/folder/myHelper.js')
or
myHelper: ['app/folder/myHelper.js', 'default']
Webpack doesn't throw 'cannot find module' on start. but I've got 'myHelper' is undefined when trying to use it. What could be wrong?
I thought I could require it on ProvidePlugin and than just use without require anywhere else.

Unable to write a CommonJS module in ScalaJS that gets "imported" in Atom editor as a plugin

What should i do if i want to export some ScalaJS methods as CommonJS module? I have the following but it doesn't seem to work:
#ScalaJSDefined
#JSExportTopLevel("default")
object SourceFetch extends js.Object {
def activate(state: js.Dynamic): Unit = {
global.console.log("activate")
}
def deactivate(): Unit = {
global.console.log("deactivate")
}
}
And yes, scalaJSModuleKind := ModuleKind.CommonJSModule is in the build.sbt.
What i want as output is a commonjs module that looks like this;
export default {
activate(state) {
console.log("activate");
}.
deactivate() {
console.log("deactivate");
}
};
What i ended up doing is to use the deprecated sbt key "scalaJSOutputWrapper" and append 'module.exports = exports["default"];' at the end of output JS file.
I did try "scalaJSUseMainModuleInitializer" but I am only able to get a hold of "module.exports" not "exports" and the value of "module.exports" is undefined.
Your above snippet does indeed correspond to the piece of ECMAScript 2015 code that you wrote. However, that does not export the methods as direct members of the module, but as members of the default object. And no, the default export is not the same as the module itself (although many people think so).
To export the functions as direct members of the module, you should write:
object SourceFetch {
#JSExportTopLevel("activate")
def activate(state: js.Dynamic): Unit = {
global.console.log("activate")
}
#JSExportTopLevel("deactivate")
def deactivate(): Unit = {
global.console.log("deactivate")
}
}

TypeScript: Avoid require statements in compiled JavaScript

In my TypeScript code I am using a third-party library called bunyan like so:
private logger: bunyan.Logger = bunyan.createLogger({name: "MyClass"});
Because TypeScript cannot resolve the variable bunyan, I do this to make the TypeScript compiler work:
import * as bunyan from "bunyan";
Unfortunately this causes the following JavaScript output:
var bunyan = require("bunyan");
The require statement will not work in the browser (when not using a requirejs implementation), so I will receive: Uncaught ReferenceError: require is not defined.
Actually I don't need the require statement in my compiled JavaScript because there is a bunyan.min.js (browserified version) which I can use for the browser. But how can I avoid the bunyan import in my TypeScript code without having the TypeScript compiler complaining about an unknown reference?
I am using TypeScript 1.8 and this is my TypeScript compiler configuration:
tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "node",
"noEmitOnError": true,
"noImplicitAny": false,
"removeComments": true,
"target": "es5"
},
"exclude": [
"node_modules",
"typings/browser",
"typings/browser.d.ts"
]
}
You should use declare to declare a module for bunyan with Logger and createLogger.
declare module bunyan {
export interface Logger {
info(message: string): any;
warn(message: string): any;
}
export function createLogger(options: any): Logger;
};
class MyClass {
private logger: bunyan.Logger = bunyan.createLogger({name: "MyClass"});
}
I would recommend using a typings declaration file like the one found here so you get the full benefit of TypeScript :)
I found out that there are two things that come into play:
Package reference
Type declaration
Explanation
In my initial code I imported bunyan which helped the TypeScript compiler to find bunyan's declaration. With the assignment of private logger: bunyan.Logger I also forced type safety on my logger variable.
To get rid off the bunyan reference (to also get rid off the compiled var bunyan = require("bunyan"); code) I needed to trick the compiler.
The TS compiler can be cheated by removing the import and telling TypeScript that there is something (any) out in the wild which is named bunyan. This can be done by writing:
declare var bunyan: any;
Because the TS compiler is tricked there is no way for it to guarantee type safety anymore, so the specific type from the logger variable needs to be removed and it's declaration must look like the following statement:
private logger: any = bunyan.createLogger({name: "MyClass"});
This bring us to the following solution:
Before
// Package reference
import * as bunyan from "bunyan";
// Type declaration
private logger: bunyan.Logger = bunyan.createLogger({name: "MyClass"});
After
// Package reference
declare var bunyan: any;
// Type declaration
private logger: any = bunyan.createLogger({name: "MyClass"});
Thanks James Monger for making this clear to me.

Typescript: Working with Other JavaScript Libraries with a single function

In typescript, I understand how to specify the shape of an external library. Consider though the case in which only a single function from the library is needed or the library is only a single (possibly overloaded) function (such as this library for the function merge). Having to call the function using the module name -dot- function name is rather verbose:
In file merge.d.ts:
declare module "merge" {
export function merge(o: Object, ...args: Object[]): Object;
export function merge(isDeep: boolean, o: Object, ...args: Object[]): Object
}
In some test file:
///<reference path="merge.d.ts"/>
import merge = require('merge');
merge.merge({x: 1}, {y: 2});
Is there a different way to do this that can effectively replace merge.merge with just merge on line 3 while still doing checking types?
ES6 destructuring will extract the specific function for you:
import { merge } from 'merge';
merge({x: 1}, {y: 2});
You don't have to change the module structure.
More examples here: http://www.2ality.com/2014/09/es6-modules-final.html
Use export =. Here is the complete example:
declare module "merge" {
interface Merge {
merge(o: Object, ...args: Object[]): Object;
merge(isDeep: boolean, o: Object, ...args: Object[]): Object;
}
var merge:Merge;
export = Merge;
}

Extending a class in another file

I have some TypeScript code that is being generated by a tool. I'd like to extend this class in another file. As of 0.9.1.1, what's the best way to go about this?
I thought maybe I could staple my additional functions onto the prototype, but this is giving various errors (which change depending what mood the compiler is in).
For example:
Foo.ts (generated by a tool)
module MyModule {
export class Dog { }
}
Bar.ts
module MyModule {
function bark(): string {return 'woof';}
Dog.prototype.bark = bark;
}
You cannot split a class definition between multiple files in TypeScript. However typescript understands how JavaScript works and will let you write idomatic JavaScript classes just fine:
module MyModule {
export function Dog(){};
}
module MyModule {
function bark(): string {return 'woof';}
Dog.prototype.bark = bark;
}
Try it online
One way around this is to use inheritance:
class BigDog extends Dog{
bark(){}
}
I have encountered your problem as well before, but I had some deeper problems. You can see from basarat's example, that simple functions can be added as an extension to the prototype, but when it comes to static functions, or other static values you might want to extend your (presumably third party) class, then the TSC will warn you, that there is no such method defined on the class statically.
My workaround was the following little hack:
module MyModule {
export function Dog(){};
}
// in the other file
if (typeof MyModule !== 'undefined'){
Cast<any>(MyModule.Dog).Create = ()=>{return new Dog();};
}
// where Cast is a hack, for TS to forcefully cast types :)
Cast<T>(element:any):T{ return element; }
This should cast MyModule.Dog, to an any object, therefore allowing attachment of any kinds of properties, functions.