I have a Typescript class which includes a generic which needs to extend another class and implement an interface. Here is an example
interface IHasImage {
imageUrl():string;
}
class Model {
}
class View<T extends Model & IHasImage> {
}
This is the sort of syntax I have seen elsewhere but is there a way of doing this in Typescript?
edit: Try pasting the following in to the playground:http://www.typescriptlang.org/Playground
...[removed edit 1 code]
edit 2: Answer and reasoning
(I apologise, the first example had a few flaws!) I have marked the correct answer below, although it probably needs a few pointers as outlined in this github issue (https://github.com/Microsoft/TypeScript/issues/1885)
Given the following code you can see the methodology works.
The only other thing to say is that trying to implement
the interface from a class that does not extend the base class also fails. However because Typescript checking is based on the structure of the object, it will succeed if you manually add the name
property to the class.
This is also why it succeeds with the ModelCorrect
which extends
but doesn't implements
.
In TypeScript, interfaces can also extend classes, but only in a way that involves inheritance. When an interface extends a class, the interface includes all class members (public and private), but without the class' implementations.
You can subtype a generic class or interface by extending or implementing it. The relationship between the type parameters of one class or interface and the type parameters of another are determined by the extends and implements clauses.
TypeScript - Generic Interface The above IProcessor is a generic interface because we used type variable <T> . The IProcessor interface includes the generic field result and the generic method process() that accepts two generic type parameters and returns a generic type. As you learned, you can use interface as type.
TypeScript fully supports generics as a way to introduce type-safety into components that accept arguments and return values whose type will be indeterminate until they are consumed later in your code.
Typescript is not so restrictive as Java or C# so you can do things like that:
interface IHasImage {
imageUrl():string;
}
class Model {
}
// use the Model class like an interface
interface IHasImageModel extends IHasImage, Model{
}
class View<T extends IHasImageModel> {
constructor(arg :T){
arg.imageUrl();
}
}
Edit: In TypeScript 1.6 you can use Intersection types:
interface IHasImage {
imageUrl():string;
}
class Model {
}
class View<T extends IHasImage & Model> {
constructor(arg :T){
arg.imageUrl();
}
}
It looks like this is the only way of doing it that I can find. Not perfectly clean but it does the right thing.
interface IHasImage extends Model{
imageUrl():string;
}
class Model {
}
class View<T extends IHasImage> {
}
Here is a screenshot from the playground verifying that it works:
Edit: Added correct workaround.
Missing in the example is what T will be:
In the example below i have added an implementation for T, that can be used as the generic constraint.
interface IHasImage {
imageUrl():string;
}
class Model {
}
class ModelWithImage extends Model implements IHasImage {
imageUrl():string
{
return "http://thepetwiki.com/images/thumb/Kitten.jpg/400px-Kitten.jpg";
}
}
class View<T extends ModelWithImage>
{
value:T;
constructor(arg:T)
{
this.value=arg;
}
}
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