Hamid Karimi
Hamid Karimi

Reputation: 735

extending interface with generic in typescript

I want to build an function which takes any object and return that object with few added properties. Something like:

    //this code doesn't work   
        function addProperties<T>(object: T): IPropertiesToAdd<T> {/*implmentions code*/};

        interface IPropertiesToAdd<T> extend T{
            on(): void;
            off(): void;
        }

//usage example
var str = new String('Hello')
addProperties(str)
str.charAt(3)
str.on() 

For the above code typescript compiler return the error that an interface can only add a class or interface, how I can express this in typescript.

Upvotes: 38

Views: 100226

Answers (3)

anlijudavid
anlijudavid

Reputation: 539

I solve the problem with:

type IModelProperty<T = Record<string, any>> = T & {
     on(): void;
     off(): void;
};

Upvotes: 9

user2278642
user2278642

Reputation:

You can create a new type alias which will allow your object to inherit the features of another object type. I found this bit of code here.

type IPropertiesToAdd<T extends {}> = T & {    // '{}' can be replaced with 'any'
    on(): void
    off(): void
};

interface ISomething {
    someValue: number
}

var extendedType: IPropertiesToAdd<ISomething> = {
    on(): void {
        console.log("switched on");
    },
    off(): void {
        console.log("switched off");
    },
    someValue: 1234,
};

I've tested this, and it seems that 'T' can be an interface, class, and an array type. I couldn't get union types to work.

This only works on anonymous objects, it can't be used for actual inheritance purposes.

Hope this helps.

Upvotes: 81

donnut
donnut

Reputation: 720

Interface IPropertiesToAdd defines a type variable T that is used to extend an interface named T. This is not possible. An interface can not be referred using a variable name; it must have a fixed name, e.g. Evnt:

interface Evnt<T> {
  name: T;
}

interface IPropertiesToAdd<T> extends Evnt<T> {
  on(): void;
  off(): void;
}

I am not sure what you are trying to achieve in your case. I have extended the example a bit, so it compiles:

function addProperties<T>(object: Evnt<T>): IPropertiesToAdd<T> {
  /* minimum implementation to comply with interface*/
  var ext:any = {};
  ext.name = object.name
  ext.on = function() {};
  ext.off = function() {};
  return ext;
};

interface Evnt<T> {
  name: T;
}

interface IPropertiesToAdd<T> extends Evnt<T> {
  on(): void;
  off(): void;
}

//usage example
var str = {name: 'Hello'}
var evnt = addProperties(str)
evnt.charAt(3); // error because evnt is not of type 
                // `string` but `IPropertiesToAdd<string>`
evnt.on()

Upvotes: 24

Related Questions