带有省略类型的TypeScript中的函数链接

带有省略类型的TypeScript中的函数链接,typescript,chaining,method-chaining,Typescript,Chaining,Method Chaining,假设我想在TypeScript中实现一个类型化函数链,但在本例中,调用函数会从返回类型中删除该函数。例如: type Omit<T, K> = Pick<T, Exclude<keyof T, K>>; interface Chainable { execute: () => Promise<void>; } interface Chain1 extends Chainable { chain1?: () => Omit&l

假设我想在TypeScript中实现一个类型化函数链,但在本例中,调用函数会从返回类型中删除该函数。例如:

type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;

interface Chainable {
  execute: () => Promise<void>;
}

interface Chain1 extends Chainable {
  chain1?: () => Omit<this, 'chain1'>;
}

interface Chain2 extends Chainable {
  chain2?: () => Omit<this, 'chain2'>;
}

let chain: Chain1 & Chain2 = {
  execute: () => null,
  chain1: () => {
    delete chain.chain1;
    return chain;
  },
  chain2: () => {
    delete chain.chain2;
    return chain;
  }
};

chain.chain1().chain2().execute(); // Using the function chain

我这样做对吗?在TypeScript中,是否可以逐步将多个省略类型组合在一起,以便返回类型连续省略属性?

我认为
的类型是在首次检查函数时确定的,然后在之后的任何时候都不会重新计算。因此
this
对于
chain2
的第二次调用仍然是原始
this
而不是
chain1
的返回类型。我不确定这是预期的行为还是bug,您可能需要检查GitHub是否存在类似问题

一种解决方法是使用将绑定到
this
的泛型类型参数为任何给定函数捕获
this
。这将确保通过功能链的正确类型流。一个小问题是,使用箭头函数无法进行打字,您需要使用常规函数并访问

type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;

interface Chainable {
    execute: () => Promise<void>;
}

interface Chain1 extends Chainable {
    chain1?: <T extends Chain1>(this: T) => Omit<T, 'chain1'>;
}

interface Chain2 extends Chainable {
    chain2?: <T extends Chain2>(this: T) => Omit<T, 'chain2'>;
}

let chain: Chain1 & Chain2 = {
    execute: () => null,
    chain1: function () {
        delete this.chain1;
        return this;
    },
    chain2: function ()  {
        delete this.chain2;
        return this;
    }
};

chain.chain1().chain2().execute(); // Using the function chain
chain.chain1().chain2().chain1().execute(); // error
类型省略=拾取;
可链接接口{
执行:()=>承诺;
}
接口Chain1扩展了可链接的{
chain1?:(this:T)=>省略;
}
接口Chain2扩展了可链接的{
chain2?:(this:T)=>省略;
}
让链:链1和链2={
执行:()=>null,
链1:函数(){
删除本条第1款;
归还这个;
},
链2:函数(){
删除本条第2款;
归还这个;
}
};
chain.chain1().chain2().execute();//使用功能链
chain.chain1().chain2().chain1().execute();//错误

使用
这个
参数是个好主意。@jcalz 10x,我现在怀疑这个是谁。我本以为他的代码会工作,我猜多态
这个
是在函数声明时确定的,之后不会重新计算。这太完美了!我不喜欢使用输入参数this
,但我没有想到使用泛型来扩展这个类。非常感谢。
type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;

interface Chainable {
    execute: () => Promise<void>;
}

interface Chain1 extends Chainable {
    chain1?: <T extends Chain1>(this: T) => Omit<T, 'chain1'>;
}

interface Chain2 extends Chainable {
    chain2?: <T extends Chain2>(this: T) => Omit<T, 'chain2'>;
}

let chain: Chain1 & Chain2 = {
    execute: () => null,
    chain1: function () {
        delete this.chain1;
        return this;
    },
    chain2: function ()  {
        delete this.chain2;
        return this;
    }
};

chain.chain1().chain2().execute(); // Using the function chain
chain.chain1().chain2().chain1().execute(); // error