Can you dynamically extend a type in typescript?
typescript
Solution
Update: It sounds like you are after truly dynamic behaviour at runtime... i.e. you don't know it will be `video`, `audio` or some other values. In this case, where you have a dynamic channel name from some source, you would have to use `[]` syntax - but there are still some
var channel = 'video;'
var data = new Sockets();
data.addChannel(channel);
// Totally dynamic / unchecked
var media = data[channel].read();
// Or
interface IChannel {
read(): { /* You could type this */ };
}
// Dynamic call, but read method and media variable typed and checked
var media = (<IChannel>data[channel]).read();
Previous answer... useful for anyone reading this question who isn't after full on dynamic behaviour (but pretty useless for Doug, sorry!)
If you want to extend an existing class, you can use inheritance:
class ClassOne {
addOne(input: number) {
return input + 1;
}
}
// ...
class ClassTwo extends ClassOne {
addTwo(input: number) {
return input + 2;
}
}
var classTwo = new ClassTwo();
var result = classTwo.addTwo(3); // 5
If you want to do this really dynamically, for example you just want to add something to an instance, you can do that too - but inheritance gives you much more for your money.
class ClassOne {
addOne(input: number) {
return input + 1;
}
}
// ...
var classOne = new ClassOne();
classOne['addTwo'] = function (input: number) {
return input + 2;
};
var result = (<any>classOne).addTwo(3); // 5
//or (nasty 'repeat the magic string version')
result = classOne['addTwo'](3);
If you are dead set on the dynamic route, a common pattern in TypeScript is to represent the structure with an interface, not a class. Interfaces (and modules, and enums) are open - so they can be extended over multiple blocks. You would need to ensure your interface and implementation were equally extended. This is the technique you use to extend built-in objects.
// NodeList is already declared in lib.d.ts - we are extending it
interface NodeList {
sayNodeList(): void;
}
NodeList.prototype.sayNodeList = function () {
alert('I say node, you say list... NODE');
}
This gives you full auto-completion and type checking.
Problem
In javascript you can do this: ``` function Test() { this.id = 1; }; Test.prototype.customize = function(key, callback) { this[key] = callback; }; var callback = function() { alert(this.id); }; var x = new Test(); x.customize('testing', callback); x.testing(); ``` Can you do a similar thing in typescript? Particularly I'm interested in having a class like: ``` class Socket { ... } class Sockets { public addChannel(name:string):void { this[name] = new Socket(); } ... } data = new Sockets(); data.addChannel('video'); data.addChannel('audio'); ... var audio = data.audio.read(); var video = data.video.read(); etc. ``` The compiler complains that there's no 'audio' or 'video' member on 'Sockets', and won't compile. Is there a way to work around that without having to manually define the properties on the container class? I know it kind of side steps the static typing rules, but I find it occasionally useful for API niceness to have something like this. edit: See the example answer I posted below; something like that works. I'll still accept any clever answer that lets me somehow manage to compile something that does something useful on the base object itself.