镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Class declarations should implicitly implement interfaces #340

Description

http://typescript.codeplex.com/workitem/1125

Following should be allowed:

interface IFoo {
    foo();
}

declare class Foo implements IFoo {}

If abstract classes are added in the future, they would inherit all interface methods as abstract (like in Java).

Activity

  1. Bartvds commented on Aug 2, 2014

    @Bartvds

    +1 It would remove a lot of code duplication on declaration files.

  2. basarat commented on Aug 2, 2014

    @basarat
    Contributor

    👍

    The kind of thing you don't know you need till you see it suggested. In the absence of this many times DT PR's break tests because they need to go to all the places and add these members. (which is fine-ish)

    More importantly for something like spacepen (used by atom.io) that implements JQuery we (the wise Masahiro Wakame (@vvakame)) just decided not put them in and leave it in a comment (otherwise we would need to fix up the definition everytime someone added a new JQuery plugin definition).

    https://github.com/borisyankov/DefinitelyTyped/blob/e9b0f608b1ca18344b2a916048594c8f30b0df10/space-pen/space-pen.d.ts#L52

    declare class View /* implements JQuery */ {
  3. basarat commented on Aug 2, 2014

    @basarat
    Contributor

    If its decided to add this, I also have breaking change proposal. I think the following should be prevented and give an error as shown:

    interface IFoo {
        foo();
    }
    
    declare class Foo implements IFoo {
        foo(); // Error: Already has member foo
    }

    That will make implementing this feature easier and consistent.

  4. mwisnicki commented on Aug 2, 2014

    @mwisnicki
    Author

    Why ? It's allowed for classes:

    declare class Foo {
        foo();
    }
    
    declare class Foo2 extends Foo {
        foo();
    }

    It's quite useful - you can put additional documentation on Foo2.foo this way.

  5. RyanCavanaugh commented on Aug 4, 2014

    @RyanCavanaugh
    Member

    The problem is that if you assume classes have their declared interface's members, it becomes very unclear/confusing what it means if you explicitly write those members:

    /* Input code */
    interface SomeInterface1 {
        getThing(x: string): Element;
    }
    
    interface SomeInterface2 {
        getThing(x: number): HTMLElement;   
    }
    
    declare class SomeClass implements SomeInterface1, SomeInterface2 {
        getThing(x: any): HTMLCanvasElement;
    }
    
    /* What does the definition of SomeClass mean? */
    
    // First answer: Same thing it meant in TypeScript 1.0, because
    // this doesn't justify a breaking change
    module Alpha {
        declare class SomeClass implements SomeInterface1, SomeInterface2 {
            getThing(x: any): HTMLCanvasElement;
        }
    }
    
    // Second answer: The class implementation is just another
    // signature, so append it to the list of signatures we got from
    // the interfaces
    module Beta {
        declare class SomeClass implements SomeInterface1, SomeInterface2 {
            getThing(x: string): Element;
            getThing(x: number): HTMLElement;   
            getThing(x: any): HTMLCanvasElement;
        }
    }
    
    // Third answer: The class implementation should come first because
    // it's the most important one (even though this creates unreachable signatures)
    module Gamma {
        declare class SomeClass implements SomeInterface1, SomeInterface2 {
            getThing(x: any): HTMLCanvasElement;
            getThing(x: number): HTMLElement;   
            getThing(x: string): Element;
        }
    }
    
    // Fourth answer: This is disallowed?
    module Delta {
        /* Breaking change, SomeClass is an error */
    }

    Then, under the proposal:

    /* Input code, changed slightly */
    interface SomeInterface1 {
        getThing(x: string): Element;
    }
    
    interface SomeInterface2 {
        getThing(x: number): HTMLElement;   
    }
    
    declare class SomeClass implements SomeInterface1, SomeInterface2 { }
    
    /* What does the definition of SomeClass mean? */
    
    // First answer: this is an error because SomeInterface1 and SomeInterface2
    // have conflicting members
    module Alpha {
        /* error */
    }
    
    // Second answer: The class is assumed to have both overloads
    module Beta {
        declare class SomeClass implements SomeInterface1, SomeInterface2 {
            getThing(x: string): Element;
            getThing(x: number): HTMLElement;   
        }
    }
    
    // Third answer: Something else?
    module Gamma {
        declare class SomeClass implements SomeInterface1, SomeInterface2 {
            /* ? */
        }
    }
  6. added
    CanonicalThis issue contains a lengthy and complete description of a particular problem, solution, or design
    on Apr 7, 2015
  7. RyanCavanaugh commented on Feb 17, 2016

    @RyanCavanaugh
    Member

    Note that in the latest version of TypeScript, you can use class/interface merging to do this:

    interface Foo {
        a: number;
    }
    
    interface Baz extends Foo { }
    class Baz {
        constructor() {
            console.log(this.a); // no error here
        }
    }

    hat tip jeffreymorlan for reminding me of this

  8. added
    CommittedThe team has roadmapped this issue
    and removed
    CanonicalThis issue contains a lengthy and complete description of a particular problem, solution, or design
    DeclinedThe issue was declined as something which matches the TypeScript vision
    Too ComplexAn issue which adding support for may be too complex for the value it adds
    on Feb 17, 2016
  9. locked and limited conversation to collaborators on Jun 18, 2018
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

    CommittedThe team has roadmapped this issueSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions