Typescript reference comment for working - visual-studio-2013

I am using Visual Studio 2013 Ultimate Update 4 and Typescript.
I have a class like MyClass.ts:
/// <reference path="interfaces/IMyClass"/>
export = MyModule;
module MyModule {
class MyClass {
constructor(myObject: IMyClass){....}
...
}
}
And another MyInterface.ts:
export = MyModule;
module MyModule {
interface IMyClass {
...
}
}
VS2013 is not acknowledging the IMyClass reference in the MyClass file (no intellisense either), but the reference is acting like VS can see it (no red underlines saying it can't find the file).
If I change the interface filename to MyInterface.d.ts, it does the same thing.
If I change the interface inside MyInterface.d.ts to this:
//export = MyModule ;
declare module MyModule {
interface IMyClass {
...
}
}
it fails as well.
If I change the interface inside MyInterface.d.ts to this:
//export = MyInterfaces ;
declare module MyInterfaces {
interface IMyClass {
...
}
}
it works.
Am I missing something? So we can only use reference comments for .d.ts files and the exported module names can be the same??
I'm finding a lot of the stuff around modules in typescript to be confusing.
Thanks in advance.

VS2013 is not acknowledging the IMyClass reference in the MyClass file (no intellisense either),
The modules MyModule between two TypeScript files that use external modules are distinct. And therefore you don't get interface IMyClass available in the second files MyModule.
Tip: You might want to review internal vs. external modules in TypeScript (hint: don't use internal ones if you are using external modules). https://www.youtube.com/watch?v=KDrWLMUY0R0&hd=1

Related

ExcelDna - Excel can't access function in base class

When Excel tries to call a method in a abstract base class i get a Run-Time error
"Cannot run Marco 'MarcoName'. The macro may not be available"
I can run code from the super class.
The code is similar to this
public abstract class MyBaseClass
{
public static bool MyMethod(string path)
{
if(Valid(path))
{return true;}
return false;
}
}
This code is in a separate assembly imported via a nuget package
The calling code is similar to the below
public class MyClass : MyBaseClass
{
public static bool MyOtherMethod()
{
return true;
}
}
Marking the methods with the "[ExcelFunction]" attribute has no effect.
I am loading the xll file like so,
Application.RegisterXLL (path)
I call the method like so,
Application.Run("MyMethod", path)
Only code in assemblies that are included in the <ExternalLibrary ... /> list in the .dna file are scanned for functions to register. Maybe your external assembly is not mentioned there.
Also, abstract types were not always considered. It looks like this changed at some point, if I look at the code that scans the assemblies here: https://github.com/Excel-DNA/ExcelDna/blob/57c2d0a499a044f6cd1c4ae2c9fbf5b084159dea/Source/ExcelDna.Integration/AssemblyLoader.cs#L93
So it might depend on your Excel-DNA version too.
Easiest might be to have a class with all the functions you want to export, where you can add the Excel-specific attributes (<ExcelFunction .../>) and just forward the calls internally.

How to use someClass.android.ts and someClass.ios.ts without errors

I'm using nativescript angular. I have a class called SomeClass that access the native API of iOS and Android separately.
I've written two files:
someclass.android.ts
export class SomeClass {
someFunction() {
if(isAndroid) {
// do some android specific code
}
}
}
someclass.ios.ts
export class SomeClass {
someFunction() {
if(isIOS) {
// do some ios specific code
}
}
}
Now, in app.component.ts, I'm using SomeClass like this:
import { SomeClass } from './../shared-code/someclass';
without .android.ts or .ios.ts, to enable nativescript to pick the right file depending on the running platform.
and then in the code, I user SomeFunction like this:
...
const someClass = new SomeClass();
someClass.someFunction();
...
With this setting, everything works perfectly on both iOS and Android, but I get the following error
error TS2307: Cannot find module './../shared-code/someclass'.
Do you have any idea how to tell nativescript/tslint to take into account the .android and .ios files and not to display this error?
Thanks
Here's the solution:
Alongside 'someclass.ios.ts' and 'someclass.android.ts', create a definitions file and name it 'someclass.d.ts' (Not index.d.ts). No need to put the files in a separate folder.
In someclass.d.ts, export declare the class like this:
export declare class SomeClass {
/**
* someFunction, is a function that does this and that (description)
*/
someFunction(): void;
}
Then, you can use this from another file like this:
In app.component.ts:
import { SomeClass } from './../shared-code/someclass';
Remember to use /someclass without any extensions.
This would solve build and tslint errors.

Typescript split solution into several projects

I used ScriptSharp before it was frozen. Since TypeScript is a developing OOP language I decided to try it. I use visual studio (if it matters). I have troubles making simple things I used to do in ScriptSharp. I didn't expect it would be that difficult.
What I want to do:
Create project A (Class Library Project) with module AssemblyA. AssemblyA module will have
some exported classes.
Create project B (Class Library Project) with module AssemblyB. AssemblyB will reference
AssemblyA types and use them as parameter types and etc.
Can you give me some guide how to make it work or sample? Thanks.
UPDATE:
What's for I can add reference to another typescript project? It would be great if output of referenced project was copied to that project.
Rather than having assemblies and modules, you have modules that can be organised into namespace-like hierarchies:
Internal Modules
Internal Module Example:
module AssemblyA {
export module ModuleA {
export class Example {
}
}
export module ModuleB {
export class Example {
}
}
}
var x = new AssemblyA.ModuleA.Example();
var y = new AssemblyA.ModuleB.Example();
You can also define these internal modules across multiple files...
modulea.ts
module AssemblyA {
export module ModuleA {
export class Example {
}
}
}
moduleb.ts
///<reference path="./modulea.ts" />
module AssemblyA {
export module ModuleB {
export class Example {
}
}
}
app.ts
///<reference path="./modulea.ts" />
///<reference path="./moduleb.ts" />
var x = new AssemblyA.ModuleA.Example();
var y = new AssemblyA.ModuleB.Example();
External Modules
And if you want to write really large applications, you can use external modules (where the file represents the module).
assemblya/modulea.ts
export class Example {
}
assemblya/moduleb.ts
export class Example {
}
app.ts
import ModuleA = require('./assemblya/modulea');
import ModuleA = require('./assemblya/modulea');
var x = new ModuleA.Example();
var y = new ModuleB.Example();
I found a workaround for my problem:
In project AssemblyA:
Specify "Combine javascript output into file" to "..\AssemblyB\AssemblyA.js".
Set up Generate Declaration files into true.
In project AssemblyB:
Add reference for intellisense in app.ts ///<reference path="../AssemblyA/AssemblyA.d.ts" />
Add reference to generated file in html: <script src="AssemblyA.js"></script>
In project B you can use any namespace aliases (for example: import AssemblyANS2 = AssemblyA.NS2;) or fully qualified name.
Put classes in different files, Use same module name and there is no need to refer to ts files.
What I didn't like is that referencing project doesn't make any sense, but I wanted steps 1-2-3-4 to be done automatically after adding reference.
Also "Redirect javascript output to directory" setting doesn't work when "Combine javascript output into one file" is specified. It's also weird that I can specify file path in second options. I expected these settings to be combined with Path.Combine.
Maybe my solution is not ideal, but it's exactly what I need. Feel free to suggest better idea.

How do I reference a Typescript enum inside a definition file

I am using Visual Studio 2013 with update 4 and Typescript 1.3 installed.
If I have a typescript file, like so:
MyEnums.ts:
export = MyEnumModule;
module MyEnumModule {
export enum AnEnum { RED, BLUE, GREEN }
}
And I have a definitions file like so:
MyDefinitions.d.ts:
declare module MyDefinitions {
interface ISomeInterface {
aProperty: string;
aMethod: () => void;
aColor: MyEnumModule.AnEnum;
}
}
I basically get an error of "Cannot find name 'MyEnumModule'"
This enum file works fine when referenced from typescript files. For instance:
SomeCode.ts:
export = MyCode;
import MyEnums = require('MyEnums');
module MyCode{
export class MyClass implements ISomeInterface {
public aColor: MyEnums.AnEnum = MyEnums.AnEnum.RED;
...and so on
My understanding is that adding either /// <reference ... or an import will not work for a .d.ts file (I tried just to be sure and it didn't appear to work either way).
Does anyone know how to reference an enum in a definition file like this?
Thanks in advance.
--Update:
Here is the error I see after trying Steve Fenton recommendations below (with a sample project I just made).
MyDefinitions.ts:
import MyEnumModule = require('../App/MyEnums');
declare module MyDefinitions {
interface ISomeInterface {
aProperty: string;
aMethod: () => void;
aColor: MyEnumModule.AnEnum;
}
}
MyEnums.ts:
export = MyEnumModule;
module MyEnumModule {
export enum AnEnum { RED, BLUE, GREEN }
}
MyClass.ts:
export = MyCode;
import MyImport = require('MyEnums');
module MyCode {
export class MyClass implements MyDefinitions.ISomeInterface {
public aColor: MyImport.AnEnum = MyImport.AnEnum.RED;
constructor() { }
aProperty: string = "";
aMethod: () => void = null;
}
}
Folder structure:
App
-MyClass.ts
-MyEnums.ts
Defintions
-MyDefintions.d.ts
Inside MyClass.ts MyDefinitions.ISomeInterface is underlined in red with hover warning "Cannot find name MyDefinitions".
I have AMD set for the project
Does anyone know how to reference an enum in a definition file like this?
There are workaround as Steve Fenton pointed out, but the system isn't designed for this. You should reference other definition files in your definition file and not reference an *implementation file * (MyEnum.ts) in a definition file.
I had a check on this and the following definition works for me, although I must admit I have never referenced "actual" code from "definition" code - but I can't think of any reason not to.
import MyEnumModule = require('MyEnumModule');
declare module MyDefinitions {
interface ISomeInterface {
aProperty: string;
aMethod: () => void;
aColor: MyEnumModule.AnEnum;
}
}
On mixing definitions and real implementations...
The type system in TypeScript is a design time and compile-time tool. When the type information is constructed at design time it makes no difference whether the type information is inferred from implementation code, taken from annotations that decorate implementations or come from an ambient declaration.
There are many use cases for mixing implementation code and ambient declarations - if you are migrating a million-line JavaScript program to TypeScript, you may not be able to migrate it from the bottom-most dependency upwards. Also, you can place ambient declarations inside of normal files - not just definition files - if you have a large program, you may not even know whether a type you place in an ambient declaration is "real" or "ambient".
The only difference between implementation code types and ambient declaration types is that the type information is right next to the implementation in real code files, and in a separate file for ambient declarations.
So... if you are having a problem using real implemented types in your ambient declaration, it is most likely caused by something that can be fixed. The example I supplied above works in a project I have in Visual Studio 2013, Update 4 - with TypeScript build configuration set to compile AMD modules. If you can share the exact details of the problem, I'm happy to help you get it working.
Having said this - if you are creating a type definition for trivial amounts of code, pasting them into a .ts file may even be faster than writing the definition - so you should make a case-by-case decision on where to spend the effort.

Is it possible require file content "as is" in TypeScript?

Typescript defines comment with xml tag <reference path=""/> to source local files to current file. But that tag could be placed only in file header before declaring any structures such us other modules.
So,
// File1.ts - correct
///<reference path="./Common.ts"/>
module Test {
export class TestClass {
}
}
// File2.ts - incorrect
module Test {
///<reference path="./Common.ts"/> // <<< Here is an compile error
export class TestClass {
}
}
Is it possible to source content of other typescript file to custom place of current file?
No. You cannot require code inplace as you have already found:
// File2.ts - incorrect
module Test {
///<reference path="./Common.ts"/> // <<< Here is an compile error
export class TestClass {
}
}
However you can effectively get the same effect by using functions.
// File1.ts - correct
///<reference path="./Common.ts"/>
module Test {
callAFunctionFoundInCommon();
export class TestClass {
}
}
In the latest version of TypeScript, it is not necessary to reference files manually like that. You can simply remove the reference and TypeScript will be able to figure everything out automatically.

Resources