你能动态扩展打字稿中的类型吗?

Dou*_*oug 18 typescript

在javascript中你可以这样做:

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();
Run Code Online (Sandbox Code Playgroud)

你能用打字稿做类似的事吗?

特别是我有兴趣有一个类:

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.
Run Code Online (Sandbox Code Playgroud)

编译器抱怨"套接字"上没有"音频"或"视频"成员,并且不会编译.有没有办法解决这个问题,而无需手动定义容器类的属性?

我知道它有点类步骤静态类型规则,但我发现偶尔有用的API很好有这样的东西.

编辑:请参阅我在下面发布的示例答案; 类似的东西.我仍然会接受任何聪明的答案,让我以某种方式设法编译一些对基础对象本身有用的东西.

Fen*_*ton 14

更新:这听起来像你后在运行时真正的动态行为...即你不知道这将是video,audio或者一些其他值.在这种情况下,如果您有来自某个源的动态通道名称,则必须使用[]语法 - 但仍有一些

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();
Run Code Online (Sandbox Code Playgroud)

以前的答案......对于阅读这个问题的人来说很有用,他们不是在完全动态行为之后(但对道格来说很无用,对不起!)

如果要扩展现有类,可以使用继承:

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
Run Code Online (Sandbox Code Playgroud)

如果你想真正动态地做这件事,例如你只想在实例中添加一些东西,你也可以这样做 - 但是继承可以为你提供更多的钱.

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);
Run Code Online (Sandbox Code Playgroud)

如果您在动态路由上设置了死区,则TypeScript中的常见模式是使用接口而不是类来表示结构.接口(以及模块和枚举)是开放的 - 因此它们可以扩展到多个块.您需要确保您的界面和实现得到同等扩展.这是用于扩展内置对象的技术.

// 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');
}
Run Code Online (Sandbox Code Playgroud)

这为您提供了完整的自动完成和类型检查.