This is something I've been doing in older versions of TypeScript and I use this method in C#, but it doesn't work in the latest 1.0 version of TypeScript.
Here's what worked in the past:
class Base<T extends Base<T>> {
public children : Array<T>;
doAction() {
this.children[0].promise(); // used to work
}
promise() : T {
return this; // used to work
}
}
class Child extends Base<Child> {
public myString: string;
}
new Child().promise().myString; // used to work
Everything used to work in harmony.
Now in the TypeScript 1.0 I get this error on the Base<T extends Base<T>>
definition:
Constraint of a type parameter cannot reference any type parameter from the same type parameter list.
How can I fix this example class to work without requiring any casts outside of the classes or casting anything to "any"? Maybe this pattern should be changed?
Constraints are the factors, within the organisation and outside it, that limit what the job-holder can do. Examples include: Resource limitations – the amounts and kinds of resources available. Legal regulations.
Common examples of constraints include insufficient information or equipment, and interruptions or inadequate help from other people.
Lack of direction is one of the most common organizational problems and it stems from two root causes: The leader or leaders rarely discuss or chart a deliberate direction or strategy for the future, or they fail to communicate a coherent message about the strategy to all members of the organization.
Though the overall definition sounds quite broad, the assessment focuses on 11 specific types of constraints: inadequate training, incorrect instruction, lack of necessary information about what to do or how to do it, poor equipment or supplies, lack of equipment or supplies, organizational rules and procedures, ...
You are no longer allowed to use T
here:
class Base<T extends Base<T>>
--------------------------^
You either have to make your class non-generic or use:
class Base<T extends Base<any>>
The reason given for this was to make the compiler simpler:
In our continued efforts to simplify the language, we're simplifying what generic constraints can entail.
The added overhead in terms of type-checking, error-reporting, and design complexity did not add enough additional expressiveness to make it worthwhile for 1.0. We may revisit this in future versions of TypeScript.
-- Breaking Changes Wiki
I accepted Steve's answer because he suggested to use Base<T extends Base<any>>
, but I wanted to keep a copy of the code change that fixed the problem on Stack Overflow:
class Base<T extends Base<any>> { // 1. Set as any
children: Array<T>;
doAction() {
this.children[0].promise();
}
promise(): T {
return <any> this; // 2. cast to any
}
}
class Child extends Base<Child> {
public myString: string;
}
new Child().promise().myString;
This requires a cast to any, but it's not so bad since it's only in the base class. This change doesn't affect anything using the Child or Base classes, so overall it was a very ideal alternative.
Update: In TS 1.7+ this can be done using a polymorphic this:
class Base {
children: Array<this>;
doAction() {
this.children[0].promise();
}
promise(): this {
return this;
}
}
class Child extends Base {
public myString: string;
}
new Child().promise().myString;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With