GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Make variable declarations open ended · Issue #819 · microsoft/TypeScript

Make variable declarations open ended #819

New issue
Copy link
New issue
Copy link
Closed
Closed
Make variable declarations open ended#819
Copy link
Labels
Needs More InfoThe issue still hasn't been fully clarifiedThe issue still hasn't been fully clarifiedNeeds ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.This issue needs a plan that clarifies the finer details of how it could be implemented.SuggestionAn idea for TypeScriptAn idea for TypeScript

Description

@clark-stevenson
Clark Stevenson (clark-stevenson)
opened on Oct 3, 2014
Issue body actions

This used to be on codeplex and I cannot find a reference here.

https://typescript.codeplex.com/workitem/917

The problem is that I have project.d.ts and lets say that it has a Point class with simple {x,y} properties.

project-plugin-coolvector.d.ts might come along tomorrow, and that Plugin JS might add a z property to the existing Point class.

If project-plugin-coolvector.d.ts attempts to export a Point class with a z property. You get a duplicate error. I looked at the JQuery plugins example on DT but project.d.ts must contain classes, since Point has a constructor.

I see no way of being able to support the direction of the project in this instance.

Reacted by Charles Samborski, Chad Retz, Chad Engler, James O'Cull, Matej Drolc, JeroenNelen, John Smart, Erik Krogh Kristensen, Simon Bengtsson, Mike Chamberlain and 8 more

Activity

Next
  1. danquirk commented on Oct 6, 2014

    @danquirk
    Dan Quirk (danquirk)
    on Oct 6, 2014
    Member
    More actions

    It's not clear there's a good way to do this for var that doesn't lead to a lot of unsafe code. It's possible there's a way to do this for classes. It would be helpful to understand why you need to have open ended classes and where open ended interfaces are insufficient.

  2. Dan Quirk (danquirk)
    added
    SuggestionAn idea for TypeScriptAn idea for TypeScript
    Needs ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.This issue needs a plan that clarifies the finer details of how it could be implemented.
    Needs More InfoThe issue still hasn't been fully clarifiedThe issue still hasn't been fully clarified
    on Oct 6, 2014
  3. clark-stevenson commented on Oct 6, 2014

    @clark-stevenson
    Clark Stevenson (clark-stevenson)
    on Oct 6, 2014
    Author
    More actions

    Thanks for your response 👍

    In this particular project, there is a Game class in JS https://github.com/photonstorm/phaser/blob/master/src/core/Game.js

    With its accompanying definition
    https://github.com/photonstorm/phaser/blob/master/build/phaser.d.ts#L1948

    And then there is a totally external plugin
    https://github.com/lewster32/phaser-plugin-isometric/blob/master/src/Isometric.js#L50

    It adds "iso" to the existing Game Class. Because the first link Game.js is a Class, it seems logical that the definition is a class. I cannot see how to make it an interface.

  4. clark-stevenson commented on Oct 26, 2014

    @clark-stevenson
    Clark Stevenson (clark-stevenson)
    on Oct 26, 2014
    Author
    More actions

    I seen this again today in a different project.

    There was a Core class, and an extension added a new method called to the Core prototype time. Since Time.js is a class, and Core.js is a class. The property time cannot be added to core when the definition for time.d.ts is added.

    I frequently come up against this problem and cannot seem to resolve it. I run into the interface suggestion but if that is the case, should classes simply be avoided?

  5. lucamorelli commented on Oct 30, 2014

    @lucamorelli
    Luca Morelli (lucamorelli)
    on Oct 30, 2014
    More actions

    well, especially for definition files may be a useful features, because I see several libraries that when included add members to existing type. I don't know if is good to add this in your own code

  6. saschanaz commented on Oct 30, 2014

    @saschanaz
    Kagami Sascha Rosylight (saschanaz)
    on Oct 30, 2014
    Contributor
    More actions

    I think classes will be required to be open-ended when browsers support subclassing from Array. https://status.modern.ie/subclassinges6
    https://people.mozilla.org/~jorendorff/es6-draft.html#sec-array-constructor

    For open-ended variables, are there some reasons not to do this?

    declare var x: SomeInterface;
    extend x: ExtensionInterface;
    //x now becomes SomeInterface + ExtensionInterface
    
    /*
    same as
    interface X { ... }
    interface X { ... }
    */
  7. joepb commented on Nov 6, 2014

    @joepb
    Joep Beusenberg (joepb)
    on Nov 6, 2014
    More actions

    In JavaScript we can extend ECMA classes:
    Date.foo = function() {...}
    One would expect this to be somehow supported by the TypeScript superset.

    Reacted by James O'Cull, John Smart, Aidan Steele, monnef, Simon Bengtsson, Haritha Wickremasinghe and David Piepgrass
  8. basarat commented on Jun 4, 2015

    @basarat
    Basarat Ali Syed (basarat)
    on Jun 4, 2015
    Contributor
    More actions

    Proposal

    If the following is declared:

    declare class Foo  {
        static bar: any;
        bas():any;
    }

    It can be extended using another declaration:

    // Amend Foo
    declare class Foo  {
        static anotherStatic: any;
        anotherMember():any;
    }

    Reason

    Dan Quirk (@danquirk)

    It would be helpful to understand why you need to have open ended classes and where open ended interfaces are insufficient.

    Really for a convinient way to model classes. Currently one needs to rewrite the original definition to make it extensible. This is not simple to explain to someone brand new to TypeScript.

    declare var Foo : FooStatic;
    interface FooStatic { // Static properties
        new (): Foo;
        bar: any;
    }
    interface Foo{ // Instance properties
        bas():any;
    }
    
    // Amend Foo 
    interface FooStatic  {
       anotherStatic: any;
    }
    interface Foo{
        anotherMember():any;
    }
    Reacted by Mike Chamberlain
  9. NathanWalker commented on Jul 20, 2015

    @NathanWalker
    Nathan Walker (NathanWalker)
    on Jul 20, 2015
    More actions

    +1 this is very frustrating to not have at the moment. Please please, need this.

  10. Pro commented on Aug 5, 2015

    @Pro
    Stefan Profanter (Pro)
    on Aug 5, 2015
    More actions

    👍

  11. adidahiya commented on Aug 5, 2015

    @adidahiya
    Adi Dahiya (adidahiya)
    on Aug 5, 2015
    Contributor
    More actions

    #2957 looks like it will cover the use case for open-ended classes

  12. lucax88x commented on Sep 16, 2015

    @lucax88x
    Luca Trazzi (lucax88x)
    on Sep 16, 2015
    More actions

    need!!!

  13. Daniel Rosenwasser (DanielRosenwasser)
    changed the title [-]Make class / variable declarations open ended[/-] [+]Make variable declarations open ended[/+] on Sep 16, 2015
  14. 18 remaining items

  15. John0x commented on Mar 9, 2017

    @John0x
    Moritz Brandes (John0x)
    on Mar 9, 2017
    More actions

    Mohamed Hegazy (@mhegazy) With Vue 2 you can access Vue plugins by the Vue class instance. For example the cookie plugin would be Vue.cookie

    Therefore I would have to extend the type declaration for the Vue class, which I can currently not do (as far as I can see) since we can't merge class declarations.

  16. mhegazy commented on Mar 9, 2017

    @mhegazy
    Mohamed Hegazy (mhegazy)
    on Mar 9, 2017
    Contributor
    More actions
    import * as Vue from "vue";
    
    declare module "vue" {
        export var plugin: any; // my new plugin
    }
    
    Vue.plugin; // OK
    new Vue(); // OK
    Reacted by Moritz Brandes and Thomas Schiet
  17. John0x commented on Mar 10, 2017

    @John0x
    Moritz Brandes (John0x)
    on Mar 10, 2017
    More actions

    Mohamed Hegazy (@mhegazy) thanks, I'll try that out, once I'm home :)
    Does it work if you have two different declaration files too?

    Original (index.d.ts and my own declaration.d.ts)?

  18. mhegazy commented on Mar 10, 2017

    @mhegazy
    Mohamed Hegazy (mhegazy)
    on Mar 10, 2017
    Contributor
    More actions

    Vue declaration comes from the declaration file coming from the Vue npm package. i do not know what is the other one.

  19. John0x commented on Mar 10, 2017

    @John0x
    Moritz Brandes (John0x)
    on Mar 10, 2017
    More actions

    Mohamed Hegazy (@mhegazy) yeah, that's the one I meant with index.d.ts)

  20. icewind commented on Mar 21, 2017

    @icewind
    Nikolay Osaulenko (icewind)
    on Mar 21, 2017
    More actions

    This is sad... Most of modules I'm using(typeorm as example) using class instead of interface in their declaration. I can extend them easily in JS but it is impossible in TS(keep type info + autocomplete).

  21. mhegazy commented on Mar 21, 2017

    @mhegazy
    Mohamed Hegazy (mhegazy)
    on Mar 21, 2017
    Contributor
    More actions

    classes are extensible through interfaces (instance side), and through namespaces (static side). not sure why is variable declarations merging or not is relevant here.

  22. maxlk commented on Jun 22, 2017

    @maxlk
    Maxim Kulikov (maxlk)
    on Jun 22, 2017
    More actions

    Mohamed Hegazy (@mhegazy) Class (instance) may be extended through interface only if it's declared in global namespace. It doesn't work when class is defined in some namespace:

    declare namespace ns {
        declare class Foo { }
        declare function getFoo(): Foo;
    }
    
    namespace ns {
        interface Foo {
            bar(): number;
        }
    }
    
    let foo: ns.Foo = ns.getFoo();
    foo.bar(); // Error: Property 'bar' does not exist on type 'Foo'

    (the same works when removing ns namespace)

    Reacted by James O'Cull
  23. manast commented on Nov 1, 2017

    @manast
    Manuel Astudillo (manast)
    on Nov 1, 2017
    More actions

    It would be quite interesting to hear from the maintainers of typescript the reason why this issue has not been addressed. Is it there a theoretical standpoint that prevents this for being implemented? Is it that you believe this issue is not important, or easy workarounds are available? Some other reason? Why is this issue still open after 3 years?

    Reacted by James O'Cull and David Rohmer
  24. jocull commented on Nov 1, 2017

    @jocull
    James O'Cull (jocull)
    on Nov 1, 2017
    More actions

    I have worked around this in particular cases by extended a local interface definition. This is not ideal, but it works like this:

    interface ResponseExt extends express.Response {
        myNewProperty: string;
    }
    

    Then you'd just declare usage of ResponseExt explicitly anywhere you use it, such as a function argument. Again, not my favorite thing, but it's the only workaround I could come up with.

  25. manast commented on Nov 1, 2017

    @manast
    Manuel Astudillo (manast)
    on Nov 1, 2017
    More actions

    James O'Cull (@jocull) yes, but what about methods? I would like to extend a class with new methods as in aspect oriented programming...

  26. jocull commented on Nov 2, 2017

    @jocull
    James O'Cull (jocull)
    on Nov 2, 2017
    More actions

    Manuel Astudillo (@manast) Would you mind putting an example here for clarity?

  27. nolakara commented on Feb 15, 2018

    @nolakara
    Naizam Olakara (nolakara)
    on Feb 15, 2018
    More actions

    +1

    Reacted by Kagami Sascha Rosylight
  28. RyanCavanaugh commented on Jun 24, 2021

    @RyanCavanaugh
    Ryan Cavanaugh (RyanCavanaugh)
    on Jun 24, 2021
    Member
    More actions

    The OP is extremely old here and references a link that doesn't work anymore. In the interim we've added external module augmentation, additional forms of permitted declaration merging, and removed some error cases that made declaration merging less ergonomic.

    With secure JS runtimes being more common (thus no arbitrary mutation to built-ins) and modules exporting immutable surface area in modern (thus you only can augment exposed endpoints, which are already eligible for declaration merging) I don't think there's any necessary work to do in this area. Open to new suggestions on more targeted areas but it's not clear that "make variable declarations open-ended" is a tractable description or the right path forward.

    Reacted by Clark Stevenson
  29. Ryan Cavanaugh (RyanCavanaugh)
    closed this as completedon Jun 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs More InfoThe issue still hasn't been fully clarifiedThe issue still hasn't been fully clarifiedNeeds ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.This issue needs a plan that clarifies the finer details of how it could be implemented.SuggestionAn idea for TypeScriptAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.