{"action":"created","issue":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/6","labels_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/6/labels{/name}","comments_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/6/comments","events_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/6/events","html_url":"https://github.com/Microsoft/TypeScript/issues/6","id":37902683,"number":6,"title":"Suggestion: abstract classes","user":{"login":"RyanCavanaugh","id":6685088,"avatar_url":"https://avatars.githubusercontent.com/u/6685088?v=3","gravatar_id":"","url":"https://api.github.com/users/RyanCavanaugh","html_url":"https://github.com/RyanCavanaugh","followers_url":"https://api.github.com/users/RyanCavanaugh/followers","following_url":"https://api.github.com/users/RyanCavanaugh/following{/other_user}","gists_url":"https://api.github.com/users/RyanCavanaugh/gists{/gist_id}","starred_url":"https://api.github.com/users/RyanCavanaugh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RyanCavanaugh/subscriptions","organizations_url":"https://api.github.com/users/RyanCavanaugh/orgs","repos_url":"https://api.github.com/users/RyanCavanaugh/repos","events_url":"https://api.github.com/users/RyanCavanaugh/events{/privacy}","received_events_url":"https://api.github.com/users/RyanCavanaugh/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/Microsoft/TypeScript/labels/In%20Discussion","name":"In Discussion","color":"556b75"},{"url":"https://api.github.com/repos/Microsoft/TypeScript/labels/Suggestion","name":"Suggestion","color":"006b75"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":63,"created_at":"2014-07-15T16:45:03Z","updated_at":"2015-02-12T16:46:26Z","closed_at":null,"body":"Support an `abstract` keyword for classes and their methods\r\n\r\nExamples:\r\n```TypeScript\r\nabstract class Base {\r\n    abstract getThing(): string;\r\n    getOtherThing() { return 'hello'; }\r\n}\r\nvar x = new Base(); // Error, 'Base' is abstract\r\n\r\n// Error, must either be 'abstract' or implement concrete 'getThing'\r\nclass Derived1 extends Base { }\r\n\r\nclass Derived2 extends Base {\r\n    getThing() { return 'hello'; }\r\n    foo() { super.getThing(); } // Error: cannot invoke abstract members through 'super'\r\n}\r\nvar x = new Derived2(); // OK\r\nvar y: Base = new Derived2(); // Also OK\r\ny.getThing(); // OK\r\ny.getOtherThing(); // OK\r\n\r\nabstract class Empty { } // OK\r\n```"},"comment":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/comments/74105370","html_url":"https://github.com/Microsoft/TypeScript/issues/6#issuecomment-74105370","issue_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/6","id":74105370,"user":{"login":"bwindels","id":274386,"avatar_url":"https://avatars.githubusercontent.com/u/274386?v=3","gravatar_id":"","url":"https://api.github.com/users/bwindels","html_url":"https://github.com/bwindels","followers_url":"https://api.github.com/users/bwindels/followers","following_url":"https://api.github.com/users/bwindels/following{/other_user}","gists_url":"https://api.github.com/users/bwindels/gists{/gist_id}","starred_url":"https://api.github.com/users/bwindels/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bwindels/subscriptions","organizations_url":"https://api.github.com/users/bwindels/orgs","repos_url":"https://api.github.com/users/bwindels/repos","events_url":"https://api.github.com/users/bwindels/events{/privacy}","received_events_url":"https://api.github.com/users/bwindels/received_events","type":"User","site_admin":false},"created_at":"2015-02-12T16:46:26Z","updated_at":"2015-02-12T16:46:26Z","body":"This would also be really useful for me.\r\n\r\nOne solution to avoid having to implement a runtime check could be to just not implement the abstract method in the abstract class in javascript, and let it throw a TypeError if you somehow manage to instantiate the abstract class and try to call an abstract method. It's not perfect, but it respects typescript philosophy of not doing anything typescript specific in the generated javascript and already helps a lot.\r\n\r\nIt could look like this:\r\n```typescript\r\nclass AbstractGreeter {\r\n\tconstructor(private name: string) {}\r\n\t\r\n\tgreet() {\r\n\t\treturn this.salutation() + \", \" + this.name;\r\n\t}\r\n\t\r\n\tabstract salutation(): string;\r\n}\r\n\r\nclass HiGreeter extends AbstractGreeter {\r\n\tsalutation(): string {\r\n\t\treturn \"hi\";\r\n\t}\r\n}\r\n\r\nvar g = new AbstractGreeter(\"Typescript\");\t//compile error\r\nvar ctor = AbstractGreeter;\r\n\r\nfunction makeMaybe(ctor): AbstractGreeter {\r\n\tif(Math.random() > 0.5) {\r\n\t\treturn new ctor(\"Typescript\");\r\n\t}\r\n\telse {\r\n\t\treturn null;\r\n\t}\r\n}\r\n\r\nvar ag1 = new AbstractGreeter(\"Typescript\"); //compile error\r\n\r\nvar hg = makeMaybe(HiGreeter); //compiles\r\nif(hg) {\r\n\tconsole.log(hg.greet()); //logs \"hi, Typescript\"\r\n}\r\n\r\nvar ag = makeMaybe(AbstractGreeter); //compiles \r\nif(ag) {\r\n\tconsole.log(ag.greet()); //throws \"TypeError: undefined is not a function\"\r\n}\r\n```\r\n\r\nWith the generated javascript looking like this, not defining ```salutation()``` in ```AbstractGreeter```:\r\n\r\n```javascript\r\nvar __extends = this.__extends || function (d, b) {\r\n    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\r\n    function __() { this.constructor = d; }\r\n    __.prototype = b.prototype;\r\n    d.prototype = new __();\r\n};\r\nvar AbstractGreeter = (function () {\r\n    function AbstractGreeter(name) {\r\n        this.name = name;\r\n    }\r\n    AbstractGreeter.prototype.greet = function () {\r\n        return this.salutation() + \", \" + this.name;\r\n    };\r\n    return AbstractGreeter;\r\n})();\r\nvar HiGreeter = (function (_super) {\r\n    __extends(HiGreeter, _super);\r\n    function HiGreeter() {\r\n        _super.apply(this, arguments);\r\n    }\r\n    HiGreeter.prototype.salutation = function () {\r\n        return \"hi\";\r\n    };\r\n    return HiGreeter;\r\n})(AbstractGreeter);\r\nvar g = new AbstractGreeter(\"Typescript\"); //compile error\r\nvar ctor = AbstractGreeter;\r\nfunction makeMaybe(ctor) {\r\n    if (Math.random() > 0.5) {\r\n        return new ctor(\"Typescript\");\r\n    }\r\n    else {\r\n        return null;\r\n    }\r\n}\r\nvar ag1 = new AbstractGreeter(\"Typescript\"); //compile error\r\nvar hg = makeMaybe(HiGreeter); //compiles\r\nif (hg) {\r\n    console.log(hg.greet()); //logs \"hi, Typescript\"\r\n}\r\nvar ag = makeMaybe(AbstractGreeter); //compiles \r\nif (ag) {\r\n    console.log(ag.greet()); //throws \"TypeError: undefined is not a function\"\r\n}\r\n```"}}