Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

type alias does not work with classes #5017

Closed
ghost opened this issue Sep 29, 2015 · 5 comments
Closed

type alias does not work with classes #5017

ghost opened this issue Sep 29, 2015 · 5 comments
Labels
Duplicate An existing issue was already created

Comments

@ghost
Copy link

ghost commented Sep 29, 2015

I defined a class:

export class TCommand<TSender, TParam, TThis> 
{
}

and created an alias for the closed type:

export type Command = TCommand<any, any, any>;

now when i try:

export class NextCommand extends Command {
}

the compiler says: Error 1 Cannot find name 'Command'

var cmd = new MOD.mvvm.Command();

Produces the same error
but i can write

var cmd: Command = null;

without errors,

Expected: to allow using this type alias for inheritance purposes.
The problem is that Typescript creates not a true alias
it produces in the output:

var NextCommand = (function (_super) {
    __extends(NextCommand, _super);
    function NextCommand() {
        _super.apply(this, arguments);
    }
    return NextCommand;
})(Command);  /// notice Command is not defined.

but it should produce

var NextCommand = (function (_super) {
    __extends(NextCommand, _super);
    function NextCommand() {
        _super.apply(this, arguments);
    }
    return NextCommand;
})(TCommand);  /// notice Command is replaced with original TCommand

That means - we don't need new definitions in the output for alias, but alias should be replaced with the original definition in the output!

@mhegazy mhegazy added the Duplicate An existing issue was already created label Sep 29, 2015
@mhegazy
Copy link
Contributor

mhegazy commented Sep 29, 2015

duplicate of #2559

@mhegazy mhegazy closed this as completed Sep 29, 2015
@ahejlsberg
Copy link
Member

A class declaration creates two entities with the same name: A type, which you can use in type annotations, and a constructor function, which you can use in expressions.

The problem is that you're exporting an alias for the type, but not the constructor function.

If you're using ES6 modules I'd suggest exporting an alias:

export class TCommand<TSender, TParam, TThis> {
}
export { TCommand as Command };

If you're using namespaces, you can do the following:

namespace Foo {
    export class TCommand<TSender, TParam, TThis> {
    }
    export import Command = Foo.TCommand;
}

@ghost
Copy link
Author

ghost commented Sep 29, 2015

@ahejlsberg
Thanks for the reply
My current workaround is to create a new class

   export class TCommand<TSender, TParam, TThis> {
   }

   export class Command extends TCommand<any, any, any> {
    }

But it produces the unneeded overhead.
But anyway thanks for the compiler, i did not manage to find a better one.
That means it is the best now.

@ahejlsberg
Copy link
Member

Thanks for the kind words.

If you're concerned with the overhead of a derived class, you could write it this way instead:

namespace Foo {
    export class TCommand<TSender, TParam, TThis>
    {
    }
    export type Command = TCommand<any, any, any>;
    export const Command: new () => Command = TCommand;
}

let x: Foo.Command = new Foo.Command();

You'd need to modify the new () => Command type to have the appropriate constructor parameters.

@ghost
Copy link
Author

ghost commented Sep 30, 2015

@ahejlsberg
Thanks very much! it is working.
Althougth the syntax is very convoluted.
For example, it is one of my definitions;

  export type Command = TCommand<any, any>;
  export const Command: new (fn_action: TAction<any>, thisObj: any, fn_canExecute: TPredicate<any>) => Command = TCommand;

  export type PropChangedCommand = mvvmMOD.TCommand<{ property: string; }, any>;
  export const PropChangedCommand: new (fn_action: mvvmMOD.TAction<{ property: string; }>, thisObj: any, fn_canExecute: mvvmMOD.TPredicate<{ property: string; }>) => PropChangedCommand = mvvmMOD.TCommand;

one of my use case is that: I want to introduce a new generic type instead an old one - nongeneric.
but the legacy code uses nongeneric version and i want it to continue to work as is, but newer code will avail of the new generic version.
I see the technical reason why the simple alias of a type is not working like a constructor function (you described this), but i don't see a reason what precludes for class type aliases to combine into the alias all aspects of the type - the constructor function and alias for the type.
Just treat the alias as the original type - internally replace every uses of it in the code with original type definition.

You can look at the code of my framework where i want that replacement
https://github.com/BBGONE/JRIAppTS/blob/master/jriappTS/jriappTS/modules/mvvm.ts

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

2 participants