我可以将未知数量的类型作为类打字稿的“类型参数”

时间:2021-04-20 00:56:26

标签: typescript

我正在编写一些打字稿代码,并遇到了这个问题。经过一些谷歌搜索后,我找不到任何可以工作的东西,但是如果没有代码,这个问题有点难以解释,所以这是我正在尝试制作的特定代码:


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 似乎不支持这一点,所以我的问题归结为:

我能否在有效代码中复制第二个信号类的行为(将未知数量的类型作为类的“类型参数”)?

1 个答案:

答案 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]);

检查TypeScript playground

相关问题