2

So I'm working on this ASP.NET (.NET 4.6, VS2015), which has all business logic writen in C#. But since it is not just presentation web, there will be a lot of logic on the client as well. So I took TypeScript as it looked like a great tool which will help me organise my client-side code with a style I'm used to from C#.

However, as I'm diving deeper and deeper, I see that TypeScript is nothing like C#. It all relates to a single problem:

TypeScript does not support simple class-per-file (or interface-per-file etc.) rule, where you could simply include several classes (interfaces..) in another file.

This would really come in handy, since I want to define my ViewModel classes and initialization scripts for each page, where I would use all of these models and utils.

Personaly, I found two "solutions"

A: Keep class-per-file rule and wrap each in a namespace like this:

// Analogy to c# using
import utils = App.Code.Utils;

namespace App.Code {
    export class ZipCodeValidator {

        public zipCode: string;

        public validate(): boolean {
            // I can use class from another 
            let stringValidator: utils.StringValidator = new utils.StringValidator();

            // TODO validation
            return true;
        }
    }
}

This solution I took from start and I was very happy with it. Until I found out that sometimes the order of compiled files is wrong. Yes, I can manualy keep referencing other files (or use _references.ts), but for me its like going back several years. I'm going to have hunderts of files (thanks to my class-per-file rule).

Also "they say" I can generate js files by namespaces, which is also great advantage so I can create files general.js, app.js and admin.js (you know what would be used where).

B: Second solution is to "properly" use Modules. As I understnad it, I can write it like this:

import { StringValidator } from "./Utils/StringValidator";

export default class ZipCodeValidator {
    public zipCode: string;

    public validate(): boolean {
        // I can use class from another 
        let stringValidator: StringValidator = new StringValidator();

        // TODO validation
        return true;
    }
}

But this means I need to import every single class manualy. Despite the fact that intellisense does not work properly using this approach, if I omit the "default" keyword, I also need to specify each class manualy. Also, I don't know about any posibility on how to separate source into different js files based on directory.

Ok, you may say that I misunderstood TypeScript. It is all about modules, right? But I will not settle with "you need to define all your classes in one module". Thats just not right. I could stay with JavaScript then.

PROBLEM with A: I need to manualy keep track of all files and maintain their correct order.

PROBLEM with B: I need to import all class by class. Solution would be if I could do something like

import * as utils from "./utils/"

But as far as I understand, this is not possible.

Summary

Could you please give me a push to the right track? Some tool, maybe some plugin or anything? I like TypeScript and I want to use it. I just refuse to do manual work in these days. I hope this question will help other guys like me.

Thanks

1
  • A nice update. I manualy updated TypeScript extension of VS (was not listed in updates) to TypeScript 2.0.6 (from 1.8) and it looks like the VisualStudio itself keeps track of the order of compiled files. So the solution A works much better right now. Now I get proper error when something is not in correct order. Doubleclick on the error brings me to the place where is this happening. But still, I need to find out which ts file/class is concened and manualy add it to _references.ts. Commented Dec 1, 2016 at 19:38

1 Answer 1

3

The way I do it is to use approach B and use modules. I then collect all the common modules in a wrapper module where I re-export them for easy importing in other modules.

An example:

AllUtils.ts

export * from './UtilClass1';
export * from './UtilClass2';
export { UtilClass3 as SomethingElse } from './UtilClass3';

This will allow use to use a single import statement to import all your classes like this:

import * as utils from './AllUtils';

let myUtil = new utils.UtilClass1();

Intellisense works for me in VS2015 using this approach. Added benefit of this is that you can omit or rename certain classes in the re-export. You will still have to add them one by one into the wrapper file but this will only have to be done once.

Sign up to request clarification or add additional context in comments.

1 Comment

Hi, thanks for answer. I will definietly upvote your answer since it adds some benefits to B, but I don't think that it can be considered as accepted answer. As you said, I still have to add it manualy to one file. Also, I don't see any benefit of being able to omit or rename certain classes. In fact, I think it's the oposite. If everyone in dev team renames single class by their own name, it can only lead to a lot of "wtf moments". Maybe this works well in Node.js, but in ASP.NET project we should all want consistent class/interfaces names. Anyway, thanks again. Martin

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.