TypeScript "use"/alias for Classes - class

Is there a way to do an alias or "use" (like PHP) for a TypeScript class/module.
Example:
If I have:
module Foo {
class Bar {}
}
Normally I have to write Foo.Bar to use it outside of the module. Is there a way I can alias that to something else, like "FooBar".
This would be really useful if you have several submodules (which my current project does), like:
module A.B.C.D {
export class E {}
}
is normally A.B.C.D.E which is silly.

According to page 82 of the old Typescript language spec, it stated that the following is possible.
So you should be able to alias "use" a module without having to reference the entire hierarchy.
module A.B.C
{
import XYZ = X.Y.Z;
export function ping(x: number) {
if (x > 0) XYZ.pong(x – 1);
}
}
module X.Y.Z
{
import ABC = A.B.C;
export function pong(x: number) {
if (x > 0) ABC.ping(x – 1);
}
}
The new Typescript language spec covers similar material in the section on Import Alias Declarations

Related

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")
}
}

Is there a way around to create TypeScript classes in closures?

I'm using IntelliJ IDEA's File Watcher to automatically compile the TypeScript files, but for some reason it's not liking classes defined within blocks / function closures:
Is there a way around this without having to move everything to the top-level / global scope?
Using the following code in TypeScript results in practically the same JavaScript that you appear to be aiming for...
namespace MY_NAMESPACE {
export class AssetService {
}
}
Resulting code:
var MY_NAMESPACE;
(function (MY_NAMESPACE) {
var AssetService = (function () {
function AssetService() {
}
return AssetService;
}());
MY_NAMESPACE.AssetService = AssetService;
})(MY_NAMESPACE || (MY_NAMESPACE = {}));
If you want to really reduce the scope, switch to external modules (AKA "modules" these days).
If you don't export the class from the module/file, it won't be visible globally, i.e. there's no reason to enclose class definitions in function scopes.
More about modules in TS: https://www.typescriptlang.org/docs/handbook/modules.html

can I use an interface for a property list?

I have an interface def
In order to use in many places, i understand I have to split it into its own file (at least with ES5 output). So:
//ICommand.ts>
interface RegExp {
$1: string;
$2: string;
$3: string;
// etc
}
interface IBotCommand {
regex: RegExp
// fixme - clearer def
// cmd: ():Output
cmd: any
}
export = IBotCommand;
//BotCommand.ts >
import ICommand = require("./ICommand");
class BotCommand {
commandList: ICommand
But this gives Error: cannot find name ICommand
Is this possible? What is the best syntax?
it seems this maybe down to my environment not recompiling these scripts.
also the RegExp definition is taken from here:
TypeScript and RegExp
and may not be fully functional
You are exporting the interface like this:
export = IBotCommand;
// but you are importing it with:
import ICommand = require('./ICommand');
With you export being the way it is, change your import to be:
import { IBotCommand } from './ICommand';
If you'd like to import it like this:
import ICommand from './ICommand';
then you will want to export it like this:
export default IBotCommand;
If you don't use default then you must use the object notation to reference your imports.
There is a caveat to the object notation, in that you could also do this:
import * as cmds from './ICommand';
// and use it like this:
class SomeClass implements cmds.IBotCommand {}

How can I export an interface that I have imported?

I am creating a library in typescript, which is spread across multiple files. I take all the classes and constants I have defines and import them into one module, which exports them all under one namespace. I have just defines an interface, and I wish to include it in the same namespace/module as all the other parts of my library. But apparently I can't.
Here's a simplified example:
/app.ts is the entry point of the application, all I do in it at the moment is include my library MyLib:
//app.ts
import myLib = require("lib/MyLib/MyLib"); // this works fine
/lib/MyLib/MyLib.ts is the file in which I import all of the things defined by MyLib, and export them together:
// lib/MyLib/MyLib.ts
import VehiclesImport = require("./transport/vehicles");
// error under VehiclesImport.IAutomobile, saying that VehiclesImport has no property IAutomobile
export var IAutomobile = VehiclesImport.IAutomobile;
export var Car = VehiclesImport.Car;
In /lib/MyLib/transport/vehicles.ts, I define several classes and interfaces of vehicles, here, I'll just show IAutomobile and Car:
// lib/MyLib/transport/vehicles.ts
export interface IAutomobile {
weight: number
}
export class Car implements IAutomobile {
weight = 3000
}
I have tried creating a class truck in MyLib.ts, which properly implements IAutomobile, and that works fine, without any error messages. The problem only seems to arise when I want to access IAutomobile outside of an 'implements' statement.
I apologize if this seems like a 'code dump', but in my opinion, this is a serious problem that I cannot access my interfaces except in a class declaration. I have searched Google for the past two hours and found nothing on the subject. Thanks for any help you can give me!
Edit: I understand that typescript interfaces are not part of the compiled javascript code, but that should not stop me from manipulating them within typescript.
Use the import keyword to bring in something into the type declaration space (as opposed to var which brings it into the variable declaration space).
This is demonstrated below. a.ts:
export interface A {
val: number;
}
To re-export this from another file b.ts:
import a = require('./a');
export import B = a.A; // Important use of import
Sample usage in some other file c.ts:
import b = require('./b');
var foo: b.B;
foo.val = 123;
interface C extends b.B {
val2:number;
}
var bar: C;
bar.val2 = 456;
The example rewritten following TS language specification:
a.ts:
export interface A {
val: number;
}
To re-export this from another file b.ts:
export {A} from './a'
Usage in some other file c.ts:
import {A} from './b'
var foo: A = {val: 2};
foo.val = 123;
interface C extends A {
val2:number;
}
var bar: C = {val: 1, val2: 3};
bar.val2 = 456;
Types can't be assigned to variables, they exist in different "declaration spaces". Classes can be assigned to variables, because they contribute their names to the type declaration space as well as defining the class objects. Interfaces only contribute to the types declaration space, so can't be referenced as values.
The language is a bit verbose, but this is spelt out in detail in section 2.3 of the language spec
foo.ts
export interface ITest {
...
}
bar.ts
import * as foo from "./foo";
export type ITest = foo.ITest;
This works to re-export types/interfaces
import type { MyInterface, MyType } from './randomModule';
export { MyInterface, MyType }
The key is the surrounding braces in the export statement. Works in TypeScript 4.7.4. Reference.
In TypeScript 3.9.6, this worked for me:
import { Foo as FooType } from './some-path';
export type Foo = FooType;

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.