aurelia / framework

The Aurelia 1 framework entry point, bringing together all the required sub-modules of Aurelia.
MIT License
11.75k stars 629 forks source link

Official TypeScript definitions? #81

Closed BalassaMarton closed 8 years ago

BalassaMarton commented 9 years ago

Are you guys planning an official Aurelia repo for the .d.ts files? I know there will be definitions in DefinitelyTyped or whatever, but the fact is, even DT contains broken or outdated definitions, and having up to date, official definitions would be very comforting.

EisenbergEffect commented 9 years ago

Yes. We are working on it :) On Apr 14, 2015 7:41 AM, "BalassaMarton" notifications@github.com wrote:

Are you guys planning an official Aurelia repo for the .d.ts files? I know there will be definitions in DefinitelyTyped or whatever, but the fact is, even DT contains broken or outdated definitions, and having up to date, official definitions would be very comforting.

— Reply to this email directly or view it on GitHub https://github.com/aurelia/framework/issues/81.

omidkrad commented 9 years ago

Awesome! I also vote for the official definitions.

BTW, for modules that are written in TypeScript, you can emit definitions from them and don't have to maintain manual .d.ts files.

cmichaelgraham commented 9 years ago

@BalassaMarton @omidkrad thanks for your interest !!

here are some links to preliminary work :)

automatic dts generation - process document

aurelia libs ported to typescript

automatically generated aurelia dts files

aurelia-framework.d.ts

omidkrad commented 9 years ago

Hi @cmichaelgraham I read the dts generation doc it's a good start but as mentioned in the document, it only gives stong-typing for the types that can be inferred by the TypeScript compiler. But we're still missing a lot, explicit type definitions, union types, enums, etc. I'm sure Aurelia team has good reasons with going with pure ES6 code, but for me the benefits from typing outweighs the fact that the Babel compiler currently has more ES6 features implemented. I wished the decision was the other way around, i.e. using TS for source code and then transcompiling to ES6. That way you'd get both .js file and .d.ts file and in the future when there are more ES6 features supported in TS you can also use those features.

EisenbergEffect commented 9 years ago

We are considering TS as an option for our main source. We can't do it now because TS doesn't support everything we need just yet. They know what we need and are working on it though.

That said, it's still a decision that needs to be made carefully. If we switch to TS that may just upset the community and ruin us. I don't know just yet. I would like to investigate further into a dual compilation strategy. My thought is that we could introduce types into the source in a way that they could be processes by Babel via Flow as well as TS at the same time. I don't know if anyone has tried that before, but it might be worth a shot.

cmichaelgraham commented 9 years ago

thanks for the great input :)

independent of the above decision about aurelia source, there is tremendous value in increasing the type specificity in the ported code which will, in turn, increase the specificity of the generated type definitions.

i am working hard to try to make sure that typescript is well supported.

omidkrad commented 9 years ago

I like the dual compilation strategy. I was thinking maybe could use Closure Compiler Type Annotations that could be translated to TS syntax in the conversion process.

EisenbergEffect commented 9 years ago

One thing is that Flow types use the same syntax as TypeScript and are already supported by Babel. So, I think that might be a better fit for us. I need to investigate a bit more. @cmichaelgraham If you are interested, this would be a related area worth looking into.

cmichaelgraham commented 9 years ago

wow - its the same syntax? that is very cool. i will put it on the list for sure :+1:

EisenbergEffect commented 9 years ago

I think it is. It doesn't have interfaces I don't think. If we were careful, we might be able to craft our code base so that it could be compiled both by TS and Babel with Flow....and that would be pretty cool.

EisenbergEffect commented 9 years ago

We could start to experiment with this on one repo first, like metadata, for example. See how it works, then go one repo at a time from there maybe.

cmichaelgraham commented 9 years ago

i'm with you 100%

omidkrad commented 9 years ago

In their announcement they said that they will be compatible with TypeScript definitions (.d.ts files). This is great, I've just started with Aurelia but I will try to help too.

cmichaelgraham commented 9 years ago

@omidkrad for reference, here is a comparison of TypeScript with Facebook Flow Type System https://github.com/Microsoft/TypeScript/issues/1265

omidkrad commented 9 years ago

I have mixed feelings about Flow, but looks like it has some more type checking and features compared to TypeScript. Stricter type checking means that code that passes Flow type checking should also pass TypeScript type checking but more features means that code that uses Flow-only features will fail if compiled as TypeScript.

omidkrad commented 9 years ago

OK, I see we're talking about the Babel Flow transformer. So we're not going to use Flow, just the typing syntax which is going to be the same as TypeScript (except for nullable types?).

What if the Aurelia build process did the following?

  1. Compile the source code as ES6 with Babel
  2. Copy the source code to .ts files
  3. Compile .ts source with TypeScript (tsc.exe)
  4. Deploy either the Babel or TS .js output based on some configuration setting, together with their Source Maps
  5. Deploy the TypeScript .d.ts output

If both compilation steps pass then we have a code that is compatible with the least common denominator of both languages. If anything fails then we get the appropriate error message from the respective compiler. Being able to configure which compiler output to deploy allows the developer to choose how they want to debug the code in the browser.

EisenbergEffect commented 9 years ago

I think something like that is a possibility. We just haven't had the opportunity to test that out just yet...

omidkrad commented 9 years ago

Which ES6 features you need in Aurelia framework that are not supported in TS yet?

EisenbergEffect commented 9 years ago

With 1.5, we have the language features we need. There are a few tooling issues related to cross-repo compiling and builds that I believer are lingering. @cmichaelgraham can comment on that.

nojaf commented 9 years ago

Any news on this?

EisenbergEffect commented 9 years ago

We are planning to experiment with a hybrid compilation strategy on a couple of our small libraries, starting next week, in order to see if we can generate all the d.ts files ourselves. In the mean time, @cmichaelgraham has a repo you can use.

delaman commented 9 years ago

I think Typescript is the way to go. I feel that using Typescript features such as 'implement/interface' will be better for making third party plugings/extensions.

Also I think enforcing the SOLID principles with Typescirpt at the Auerlia library level will promote higher QA standards for the community in general.

Serhioromano commented 9 years ago

Please, allow me to add my one cent for TS. I think is is said enough in @cmichaelgraham Aurelia/TS article's comments in the Aurelia blog.

It make sense to switch to TS for many reasons. And I am personally not for dual compilation strategy. This is not something that should be this flexible. I'll explain why if you allow me.

We all learn from others. We read something there and there, then we discover something on our own. If there will be 2 ways to compile Aurelia, one will become more popular and another one less. All will depends what in particular will be described in tutorials over internet.

And if at the end people will use mostly one method, another one will not worth efforts to be supported.

At the end of the day, there will be only one method left anyway.

And another reason that might sound not significant or not true, but to be 2 different method of compiling would be confusing. If I would be and new to Aurelia and just stared, then I read one article then another and in both of them different methods described I would have a question, which one is better, what are difference, ....

I understand that TS is not yet ready for Aurelia just now. But I would definitely look at TS as the ONLY way in the future.

Sorry if sound silly. If my post is unapropriate, you can delete it.

francoishill commented 9 years ago

I agree with you 100%. It makes sense to only support one. And since any JS file is already a valid TS file, I would go with TS. Because typescript only adds extra functionality to JS and does not remove anything.

On Mon, 8 Jun 2015 at 07:37 Sergey Romanov notifications@github.com wrote:

Please, allow me to add my one cent for TS. I think is is said enough in @cmichaelgraham https://github.com/cmichaelgraham Aurelia/TS http://blog.durandal.io/2015/05/06/getting-started-with-aurelia-and-typescript/ article's comments in the Aurelia blog.

It make sense to switch to TS for many reasons. And I am personally not for dual compilation strategy. This is not something that should be this flexible. I'll explain why if you allow me.

We all learn from others. We read something there and there, then we discover something on our own. If there will be 2 ways to compile Aurelia, one will become more popular and another one less. All will depends what in particular will be described in tutorials over internet.

And if at the end people will use mostly one method, another one will not worth efforts to be supported.

At the end of the day, there will be only one method left anyway.

And another reason that might sound not significant or not true, but to be 2 different method of compiling would be confusing. If I would be and new to Aurelia and just stared, then I read one article then another and in both of them different methods described I would have a question, which one is better, what are difference, ....

I understand that TS is not yet ready for Aurelia just now. But I would definitely look at TS as the ONLY way in the future.

Sorry if sound silly. If my post is unapropriate, you can delete it.

— Reply to this email directly or view it on GitHub https://github.com/aurelia/framework/issues/81#issuecomment-109869030.

kristianmandrup commented 9 years ago

I agree :) Time to gear up a level.

RomainLanz commented 9 years ago

I also agree with you.

TypeScript IS JavaScript with good sugar!

npelletm commented 9 years ago

I also 100% agree.

delaman commented 9 years ago

Also if TypeScript is used there would be no need to maintain a DefinitelyTyped for Auerlia and its libraries.

omidkrad commented 9 years ago

@EisenbergEffect @cmichaelgraham can you please elaborate a little about the build steps in the hybrid compilation strategy you're talking about? Is it going to be anything along the lines of what I described above?

EisenbergEffect commented 9 years ago

We need to do some experimentation....it's up next.

YipYipX4 commented 9 years ago

I'll add my vote here for going "all in" with TypeScript. That way, you'll be able to use 100% of the TypeScript features (interfaces, etc.) and not suffer from being restricted to the lowest common denominator. Don't forget how Angular suffers from trying to support Dart in addition to JS!

dpinart commented 9 years ago

My vote for TypeScript too

ghaddon1 commented 9 years ago

I vote for TypeScript. I like having one way to do all things "RIGHT".

On Tue, Jun 9, 2015 at 2:06 PM, dpinart notifications@github.com wrote:

My vote for TypeScript too

— Reply to this email directly or view it on GitHub https://github.com/aurelia/framework/issues/81#issuecomment-110504553.

omidkrad commented 9 years ago

I totally understand Aurelia team's cautiousness about this. There are more frameworks emerging such as WebRx that are going all TS, and there are different takes on this. For example, in this review about WebRx's choice of TypeScript you read:

Clearly the use of Typescript means there are people who will refuse to use the framework regardless of whether it works for their use case. Other people are going to be attracted exactly because it uses Typescript.

Should also note that using TS for the framework does not mean that you have to use TS to use it. It is just JavaScript at the end.

smolinari commented 9 years ago

The right thing to do is to improve JS.

Scott

omidkrad commented 9 years ago

@smolinari ES7 has a proposal for Typed Objects. This would allow for optional static typing that can be used for type checking at compile-time and for optimizing performance at run-time. But we don't want to wait for JS. TypeScript already gives us the tooling that we need, which will be mostly compatible with a future ECMAScript that supports this. We need to have types today.

smolinari commented 9 years ago

I understand. However, I feel any rallying for change should be pointed in the direction of the JS makers and not at the makers of Aurelia or any other JS framework. Though, now seeing their website and their "communication channels" for the first time, it is no wonder why the rallying is directed at the framework makers.

Scott

aluanhaddad commented 9 years ago

I think TypeScript is the way to go for a number of reasons but the most important one is stability. Elaborating a bit, TypeScript is a standardized, well specified language that has a dedicated team of veteran language designers working on it fulltime. Additionally, there is no guarantee that ES7 will ultimately support some of the forward looking features Aurelia leverages, such as decorators, whereas TypeScript already does. It seems very unlikely that TypeScript will drop these features.

That said, I think it ultimately comes down to consumer confidence. When first came across Aurelia, I found it very appealing, particularly compared to Angular and what I had seen of Angular 2, but the approach of targeting and encouraging the use of a hypothetical programming language (ES7) made me, and probably others, somewhat uneasy for a number of reasons. It couples things like IDE support and backwards compatibility very tightly to both the framework and a future version of ECMAScript which may never exist as predicted.

When the Angular 2 team announced at Build 2015 that they were switching to TypeScript, abandoning the AtScript project, they said it was a relief that they no longer had to deliver both a language and a framework. If ECMAScript 7 does not turn out as expected the Aurelia team could end up having to maintain the current prospective version of ES7 as an independent language, as would have the Angular 2 team had they not abandoned AtScript.

Just my two cents.

atsu85 commented 9 years ago

+1 for porting Aurelia sources to TypeScript and maintaining it in TypeScript.

As I understand, by now there is nothing missing from TypeScript 1.5 that Aurelia needs (or could take great advantage of).

@cmichaelgraham has done a great job with figuring out some kind of process to manually provide some support for TypeScript, but current approach has following main flaws: 1) type definitions mostly just contain names of the classes, fields and functions, but type information about fields, function parameters and return types are mostly just left as "any" type, that doesn't help much in many cases. Also generic type information is often not added where it could help other developers a lot. 2) it requires manual work (too much, to produce good quality type definitions) 3) type definitions are not kept up to date

I guess one reason why Aurelia team is (and should be) careful about porting source to TypeScript is potential to scare some developers with TypeScript. I don't think it is a problem. Having source in TypeScript doesn't mean that all the examples need to be ported from ES6 syntax to TypeScript syntax (actually I haven't missed samples with TS syntax, but it certainly wouldn't hurt community have them in parallel with ES6 syntax). Secondly, part of the developers community who are not familiar with TypeScript might also benefit from seeing Aurelia source code in ES6 syntax (in addition to TypeScript source and older ES used in production) - since TypeScript v1.4 this is also possible (just compile the same source second time with target ES6).

I'd really like to use official TypeScript declarations to get the best development speed.

Regards, Ats

kristianmandrup commented 9 years ago

If you are interested, I did some major grunt work to make Aurelia typescript definitely typed bindings using work by @cmichaelgraham, to be compatible with typescript package manager. Just needs some more luv ❤️ and effort... Aurelia-DefinitelyTyped

atsu85 commented 9 years ago

@kristianmandrup I'm interested

kristianmandrup commented 9 years ago

Then checkout https://github.com/kristianmandrup/aurelia-definitely-typed

cmichaelgraham commented 9 years ago

update:

looking at route-recognizer branch as a model for each aurelia repo

created PR to fix the generated index.d.ts file's module name https://github.com/YoloDev/babel-dts-generator/pull/3

here is the generated index.d.ts file:

declare module 'aurelia-route-recognizer' {
  import core from 'core-js';
  export interface RouteHandler {
    name: string;
  }
  export interface ConfigurableRoute {
    path: string;
    handler: RouteHandler;
  }
  export interface HandlerEntry {
    handler: RouteHandler;
    names: string[];
  }
  export interface RecognizedRoute {
    handler: RouteHandler;
    params: Object;
    isDynamic: boolean;
  }
  export class RouteRecognizer {
    constructor();
    add(route: ConfigurableRoute | ConfigurableRoute[]): any;
    handlersFor(name: string): HandlerEntry[];
    hasRoute(name: string): boolean;
    generate(name: string, params: Object): string;
    generateQueryString(params: Object): string;
    parseQueryString(queryString: string): Object;
    recognize(path: string): RecognizedRoute[];
  }
  class RecognizeResults {
    constructor(queryParams: Object);
  }
  export class StaticSegment {
    constructor(string: any);
    eachChar(callback: any): any;
    regex(): any;
    generate(): any;
  }
  export class DynamicSegment {
    constructor(name: any);
    eachChar(callback: any): any;
    regex(): any;
    generate(params: any, consumed: any): any;
  }
  export class StarSegment {
    constructor(name: any);
    eachChar(callback: any): any;
    regex(): any;
    generate(params: any, consumed: any): any;
  }
  export class EpsilonSegment {
    eachChar(): any;
    regex(): any;
    generate(): any;
  }
  export class State {
    constructor(charSpec: any);
    get(charSpec: any): any;
    put(charSpec: any): any;
    match(ch: any): any;
  }
}
EisenbergEffect commented 9 years ago

@cmichaelgraham I'm wondering, could we remove the core-js import from the type definition file? What happens when you try to use this d.ts to code against? Any issues with or without that part?

cmichaelgraham commented 9 years ago

once we have a few repos generating types, i can experiment. it seems to me that we would not need it.

npelletm commented 9 years ago

I really want to contribute to add TypeScript type definitions. @cmichaelgraham : Is it possible to update/create a guide like this TypeScript generating guidance. With this process, contributors could add types annotations on Aurelia JavaScript source code in differents aurelia repos.

Sorry for my poor english...

cmichaelgraham commented 9 years ago

your english is fine :+1: once we get the pattern for parameter typing, interface declaration and usage, and basics (like declaring class members), changes to the repos for typescript typing will be the same as regular pull requests for other code changes :+1:

npelletm commented 9 years ago

Ok I'm waiting the signal ^^

wardbell commented 9 years ago

@cmichaelgraham Are you thinking about generating documentation into the d.ts as well? I don't see that in your example.

I realize that most people have their eyes on the benefits of type constraints. But there is huge value in propagating some meaning into the intellisense along with syntax.

It's not hard to pass those comments along to the d.ts.

Maybe there just aren't docs in the source code?

cmichaelgraham commented 9 years ago

@wardbell great call !! :) :)

ping @EisenbergEffect

shazam !! needs some formatting, but making progress...

babel-dts-generator with inline comments:

declare module 'aurelia-route-recognizer' {
  import core from 'core-js';
  export interface RouteHandler {
    name: string;
  }
  export interface ConfigurableRoute {
    path: string;
    handler: RouteHandler;
  }
  export interface HandlerEntry {
    handler: RouteHandler;
    names: string[];
  }
  export interface RecognizedRoute {
    handler: RouteHandler;
    params: Object;
    isDynamic: boolean;
  }
  export interface CharSpec {
    invalidChars?: string;
    validChars?: string;
    repeat?: boolean;
  }

  /**
   * Class that parses route patterns and matches path strings.
   *
   * @class RouteRecognizer
   * @constructor
   */
  export class RouteRecognizer {
    constructor();

    /**
       * Parse a route pattern and add it to the collection of recognized routes.
       *
       * @method add
       * @param {Object} route The route to add.
       */
    add(route: ConfigurableRoute | ConfigurableRoute[]): State;

    /**
       * Retrieve the handlers registered for the named route.
       *
       * @method handlersFor
       * @param {String} name The name of the route.
       * @return {Array} The handlers.
       */
    handlersFor(name: string): HandlerEntry[];

    /**
       * Check if this RouteRecognizer recognizes a named route.
       *
       * @method hasRoute
       * @param {String} name The name of the route.
       * @return {Boolean} True if the named route is recognized.
       */
    hasRoute(name: string): boolean;

    /**
       * Generate a path and query string from a route name and params object.
       *
       * @method generate
       * @param {String} name The name of the route.
       * @param {Object} params The route params to use when populating the pattern.
       *  Properties not required by the pattern will be appended to the query string.
       * @return {String} The generated absolute path and query string.
       */
    generate(name: string, params: Object): string;

    /**
       * Generate a query string from an object.
       *
       * @method generateQueryString
       * @param {Object} params Object containing the keys and values to be used.
       * @return {String} The generated query string, including leading '?'.
       */
    generateQueryString(params: Object): string;

    /**
       * Parse a query string.
       *
       * @method parseQueryString
       * @param {String} The query string to parse.
       * @return {Object} Object with keys and values mapped from the query string.
       */
    parseQueryString(queryString: string): Object;

    /**
       * Match a path string against registered route patterns.
       *
       * @method recognize
       * @param {String} path The path to attempt to match.
       * @return {Array} Array of objects containing `handler`, `params`, and
       *  `isDynanic` values for the matched route(s), or undefined if no match
       *  was found.
       */
    recognize(path: string): RecognizedRoute[];
  }
  class RecognizeResults {
    constructor(queryParams: Object);
  }

  //  A Segment represents a segment in the original route description.
  //  Each Segment type provides an `eachChar` and `regex` method.
  // 
  //  The `eachChar` method invokes the callback with one or more character
  //  specifications. A character specification consumes one or more input
  //  characters.
  // 
  //  The `regex` method returns a regex fragment for the segment. If the
  //  segment is a dynamic or star segment, the regex fragment also includes
  //  a capture.
  // 
  //  A character specification contains:
  // 
  //  * `validChars`: a String with a list of all valid characters, or
  //  * `invalidChars`: a String with a list of all invalid characters
  //  * `repeat`: true if the character specification can repeat
  export class StaticSegment {
    constructor(string: string);
    eachChar(callback: (spec: CharSpec) => void): any;
    regex(): string;
    generate(params: Object, consumed: Object): string;
  }
  export class DynamicSegment {
    constructor(name: string);
    eachChar(callback: (spec: CharSpec) => void): any;
    regex(): string;
    generate(params: Object, consumed: Object): string;
  }
  export class StarSegment {
    constructor(name: string);
    eachChar(callback: (spec: CharSpec) => void): any;
    regex(): string;
    generate(params: Object, consumed: Object): string;
  }
  export class EpsilonSegment {
    eachChar(callback: (spec: CharSpec) => void): any;
    regex(): string;
    generate(params: Object, consumed: Object): string;
  }

  //  A State has a character specification and (`charSpec`) and a list of possible
  //  subsequent states (`nextStates`).
  // 
  //  If a State is an accepting state, it will also have several additional
  //  properties:
  // 
  //  * `regex`: A regular expression that is used to extract parameters from paths
  //    that reached this accepting state.
  //  * `handlers`: Information on how to convert the list of captures into calls
  //    to registered handlers with the specified parameters.
  //  * `types`: How many static, dynamic, or star segments in this route. Used to
  //    decide which route to use if multiple registered routes match a path.
  // 
  //  Currently, State is implemented naively by looping over `nextStates` and
  //  comparing a character specification against a character. A more efficient
  //  implementation would use a hash of keys pointing at one or more next states.
  export class State {
    constructor(charSpec: CharSpec);
    get(charSpec: CharSpec): State;
    put(charSpec: CharSpec): State;

    //  Find a list of child states matching the next character
    match(ch: string): State[];
  }
}