簡體   English   中英

Typescript - 嵌套箭頭 function 打字

[英]Typescript - Nested arrow function typing

我有這個代碼用於推遲執行 function

export type DeferredFunction<T> = () => T | PromiseLike<T>;

export class Deferrable<T> {
  protected df: DeferredFunction<T>;

  constructor(df: DeferredFunction<T>) {
    this.df = df;
  }

  public async execute(): Promise<T> {
    return this.df();
  }
}

export const defer = <T>(df: DeferredFunction<T>): Deferrable<T> => new Deferrable<T>(df);

效果很好,我可以運行類似的代碼

await defer(() => someFunction('foo', 'bar')).execute();

但我想要做的是輸入DeferredFunction以一種我可以指定內部函數簽名但我無法讓它工作的方式。 在一般情況下,上述方法有效,但是當我想限制 arguments 以使其特定於某種類型的 function 時,我沒有那種控制權。

為清楚起見,我希望能夠輸入內部函數的輸入,例如(例如)

export type InnerDeferredFunction<T> = (a: string, b: number, c: SomeObjectType) => T | PromiseLike<T>

任何幫助將不勝感激!

你在說什么“內部功能”? someFunction嗎? 如果是這樣,那么DeferredFunction<T>的類型就沒有句柄,因為它是由DeferredFunction<T>實現調用的 function 。 在 TypeScript 中沒有辦法指定“一個 function 的實現必須調用一個 function 類型(x: string, y: number, z: boolean) => string 實現細節不是函數調用簽名的一部分。


我可以想象開始解決此問題的唯一方法是讓DeferredFunction<T>接受您要調用的內部 function 以及要調用它的 arguments 列表作為參數。 這可能不是您要尋找的,但它是類型系統可以表示的最接近的。

像這樣的東西:

export type InnerDeferredFunction<T, A extends any[]> = (...args: A) => T | PromiseLike<T>;
export type ZeroArgDeferredFunction<T> = InnerDeferredFunction<T, []>

在這里,我保留A泛型,但您可以將其指定為 arguments 的一些硬編碼列表。 我已將您的DeferredFunction重命名為ZeroArgDeferredFunction ,以明確表示它不需要 arguments。

但現在Deferrable需要了解TA

export class Deferrable<T, A extends any[]> {
  protected df: ZeroArgDeferredFunction<T>;

  constructor(df: InnerDeferredFunction<T, A>, ...args: A) {
    this.df = () => df(...args);
  }

  public async execute(): Promise<T> {
    return this.df();
  }
}

您可以看到,您必須通過將內部 function 及其 arguments 傳遞給它來構造一個,並且ZeroArgDeferredFunction是在構造函數內部構建的,並且沒有傳入。

定義defer()有不同的方法。 它可以是new Deferrable的一個薄包裝,就像你擁有它的方式一樣,或者你可以想象將它拆分,以便 args 出現在第一位:

export const defer = <A extends any[]>(...args: A) => <T>(
  df: InnerDeferredFunction<T, A>): Deferrable<T, A> => new Deferrable<T, A>(df, ...args);

然后你可以像這樣測試它:

function someFunction(x: string, y: string) {
  return (x + y).length;
}
function anotherFunction(x: number, y: number) {
  return (x * y).toFixed()
}

const deferFooBar = defer('foo', 'bar');
await deferFooBar(someFunction).execute(); // okay
await deferFooBar(anotherFunction); // error! string is not assignable to number

一旦調用deferFooBar('foo', 'bar') ,返回的值將只接受可以使用 arguments foo'bar'安全調用的函數。 這意味着someFunction將被接受,而anotherFunction將被拒絕。


好的,希望有幫助; 祝你好運!

Playground 代碼鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM