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

error TS2304 for type definitions with generic assignment #7578

Closed
0815fox opened this issue Mar 18, 2016 · 4 comments
Closed

error TS2304 for type definitions with generic assignment #7578

0815fox opened this issue Mar 18, 2016 · 4 comments
Labels
Duplicate An existing issue was already created

Comments

@0815fox
Copy link

0815fox commented Mar 18, 2016

For:

class Foo<T> {

}

let x = new Foo();

type Y = Foo<string>;

let y = new Y();

tsc complains:

test.ts(9,13): error TS2304: Cannot find name 'Y'.

I would expect the code to be valid. If it were not valid - for which ever reason - then it should be line 7 which it complains about.
Btw. Seems to make no difference, whether i assign T to a literal type like string, or another class.
Of course, as workaround this also works:

class Y extends Foo<string> {};

However, this generates unnecessary runtime code. (e.g. ES5):

var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var Foo = (function () {
    function Foo() {
    }
    return Foo;
}());
var x = new Foo();
var Y = (function (_super) {
    __extends(Y, _super);
    function Y() {
        _super.apply(this, arguments);
    }
    return Y;
}(Foo));
;
var y = new Y();

Not sure, whether it would be valid to treat empty subclasses like an alias instead of prototypic inheritance.
Also interesting the free floating semi-colon right at the end.

$ tsc -v
Version 1.8.2
@mhegazy
Copy link
Contributor

mhegazy commented Mar 18, 2016

Types do not exist at runtime, they are just design time constructs that help guide the compiler to understand your code. For instance interfaces have no runtime manifestation.
type Y = Foo<string>; is a type alias; and thus it is just like an interface. the new expression in new Y(); assumes a value called Y exists at runtime, but that is not the case.
A class is really an interface (instance type) and a variable (constructor function), so you can achieve this by spiting your definition into two. There is still a missing piece though, which is trafficking the generic type between he constructor and the instance correctly. for that the feature request is tracked in #2559

@mhegazy mhegazy closed this as completed Mar 18, 2016
@mhegazy
Copy link
Contributor

mhegazy commented Mar 18, 2016

This is a duplicate of #2552.

@mhegazy mhegazy added the Duplicate An existing issue was already created label Mar 18, 2016
@0815fox
Copy link
Author

0815fox commented Mar 18, 2016

Well, I have to accept that.
Still disagree with your argument - it just explains why it is as it is, not why is has to be like that.
Alias is for me a placeholder. So when one defines Frank as an alias for Mohamed, then he'd expect Frank to work just like Mohamed. But you are right, under the hood there is no Frank, so the compiler has to be smart enough to keep track of aliases and when the programmer writes "new Y()", it should see: ah Y is an alias for X, so i generate "new X()" instead.

@RyanCavanaugh
Copy link
Member

#2559 is probably a closer duplicate

@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

3 participants