-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Generic class interface for an abstract class in TS1.6? #4693
Comments
@mhegazy and I had a recent conversation about this and the question we were wrestling with was whether it is the class constructor that is aware of abstractness or if it is the prototype that is abstract because it doesn't implement expected methods. |
@billccn can you shed some light on how this is used, and how you want to use abstract classes with them? |
Hi, I use the What I really want is a typing syntax that expresses the relationship between an expression that evaluates to a In TS1.6, the expression does not have to be new-able. For example, classes with private constructors, abstract classes or everything that is allowed on the RHS of Personally, I see three possible solutions (can all be combined):
|
@mhegazy, on #4709 (comment), @OlegDokuka was interested in specifying a catch-all type for classes to decorate, but not being able to specify that the type could be abstract limited the approach. |
In my opinion, the best thing that would be is create in native code. It should provide two main things: Base idea
The first one should be something like this: type Class = <T>{
new (...args: any[]): T;
}; it can be used something like this function newInstance<T>(clazz:Class<T>):<T>{
} The second one should looks like this: type Class = {
new (...args: any[]): any; //may be it should be Object instead of any
}; it can be used like that function newInstance(clazz:Class):any{
} Both cases should be in the TS system. But in generic case The type of var a:Class;
var b:Class<Something> = Something;
a = b; // here we hide type
var c:Something = new a() //here we can get compiler exception that it should be up cast Using with Abstract classIn this case if we support code above the TSs compiler can check in compile time what type is passed - for example: abstract class TestWithAbstractKW{
}
var clazz :Class<TestWithAbstractKW> = TestWithAbstractKW;
var a = new clazz() //here we get compiler error that abstract class cannot be directly instantiated
function testInGeneric<T>(clazz:Class<T>){
var a = new clazz();
}
testInGeneric(clazz); // everything is okay, but in runtime we get exception that abstract class can not be directly instantiated. As you can see I haven`t proposed any kind of JS code yet, because it just compiler improvement here. The last one ideaI heard that TypeScript 2.0 (AtScript) will give us many features like types manipulations at runtime. It would be cool if It would be cool if we would do something like var clazz:Class<Something>;
var abstract:boolean = clazz.isAbstract()
var implementedInsterfaces:Class[] = clazz.listInterfaces();
var fields: PropertyDescriptor[] = abstractclazz.fields();
var methods: PropertyDescriptor[] = clazz.methods(); That is all. P.S. I hope my idea will be useful |
@billccn, just to make sure i understand the issue.. function checkedCast<T>(x: any, cls: IClass<T>): T {
if (x instanceof cls)
return <T>x;
else
throw new Error("not cls");
}
class C {
}
abstract class A {
}
var c = checkedCast({}, C); // OK
var a = checkedCast({}, A); // Error, A is abstract are there other use cases? |
@mhegazy (Sorry, lost track of this thread.) I have two uses for it, one as you showed above and another one which creats a sub-class of the given argument at run time. (The latter is a replacement of the |
so why not just use |
We choke if you actually try to drop something of that type into an extends block: interface IClass<T> extends Function {
new (...args: any[]): T;
}
type Extendsable<T> = IClass<T>|Function;
function makeClass<T>(a: Extendsable<T>) {
return class extends a {}
} When it's a union we say it's not a constructor function type, and when it's just So I guess the simple question would be to ask what is the broadest way to type |
but this is not the scenario @billccn is describing. we are talking about generic helper functions that can reason about classes. extends clause is a bit of a special case. |
@billccn does #4693 (comment) addresses the issue? |
please reopen if there is more information to consider. |
I use the following definition in some generic code to capture the type of a class argument:
However, this does not work if the class in question is abstract. Is there any alternative for this? If not, can some syntax be added to support this?
The text was updated successfully, but these errors were encountered: