我正在编写一些打字稿代码,并遇到了这个问题。经过一些谷歌搜索后,我找不到任何可以工作的东西,但是如果没有代码,这个问题有点难以解释,所以这是我正在尝试制作的特定代码:
export class Signal<T> {
public readonly listeners: ((arg: T) => any)[];
constructor(){
this.listeners = [];
}
addListener(listener: (arg: T) => any) {
assert(!this.listeners.includes(listener), "Signal listener was added twice")
this.listeners.push(listener);
}
removeListener(listener: (arg: T) => any) {
const index = this.listeners.indexOf(listener);
if(index != -1){
this.listeners.splice(index, 1)
}
}
dispatch(arg: T){
for(let i = this.listeners.length - 1; i > -1; i--){
this.listeners[i](arg);
}
}
}
这只是一个类型化的信号,类似于事件监听器。你可以这样使用它:
const strSignal = new Signal<string>();
strSignal.addListener((str /* TSC now knows this is a string */) => console.log(str));
strSignal.dispatch("Hello World");
然而,我的问题是更复杂的回调,我想要多个参数:
const complexSignal = new Signal<string, number>();
complexSignal.addListener((str /* string */, num /* type error */) => console.log(str + (num * 2)));
complexSignal.dispatch("Hello World", 3);
显然,尖括号内的第二种类型被忽略了,然后传入addListener
的函数不符合要求的类型((arg: T) => any
),抛出类型错误。
我想做的是使用类似于扩展数组的东西,可能是这样的:
export class Signal<...T> {
public readonly listeners: ((...args: T) => any)[];
constructor(){
this.listeners = [];
}
addListener(listener: (...args: T) => any) {
this.listeners.push(listener);
}
removeListener(listener: (...args: T) => any) {
const index = this.listeners.indexOf(listener);
if(index != -1){
this.listeners.splice(index, 1)
}
}
dispatch(...args: T){
for(let i = this.listeners.length - 1; i > -1; i--){
this.listeners[i](...args);
}
}
}
这将像这样使用:
const complexSignal = new Signal<string, number>();
complexSignal.addListener((str /* T[0] = string */, num /* T[1] = number */) => console.log(str + (num * 2)));
complexSignal.dispatch("Hello World", 3);
Typescript 似乎不支持这一点,所以我的问题归结为:
我能否在有效代码中复制第二个信号类的行为(将未知数量的类型作为类的“类型参数”)?
答案 0 :(得分:1)
您可以使用元组类型执行此操作,而无需更改您现有的类。
// Before
const complexSignal = new Signal<string, number>();
complexSignal.addListener((str /* T[0] = string */, num /* T[1] = number */) => console.log(str + (num * 2)));
complexSignal.dispatch("Hello World", 3);
// After
const complexSignal = new Signal<[string, number]>();
complexSignal.addListener(([str /* T[0] = string */, num /* T[1] = number */]) => console.log(str + (num * 2)));
complexSignal.dispatch(["Hello World", 3]);