javascript - Cum să rezolvi eroarea: un argument spread trebuie să aibă fie un tip tuple, fie să fie transmis unui parametru rest


Dezvolt o clasă wrapper, care poate apela metoda unei instanțe interne cu un argument de tip șir de caractere.

Întregul cod este ca mai jos.

class Inner {
  public prop1: string = 'publicProp';
  private prop2: string = 'privateProp';

  method1(param1: string) {
    console.log(`${param1}`);
  }
  method2(param1: number, param2: number) {
    console.log(`${param1}, ${param2}`);
  }
}

Această clasă este clasa originală și are funcții de bază.

type Fn = (...args: any) => any;

Acesta este tipul necesar mai jos

class Outer {
  private inner = new Inner();

  // I want proxy's second parameter's type will be changed according to first parameter's value
  public proxy<
    // F type is callable member's key
    F extends keyof {
      [K in keyof Inner as Inner[K] extends Fn ? K : never]: any;
    },
    // P type will be changed according to first argument type.
    P extends Parameters<Inner[F]>,
  >(name: F, ...args: P) {
    const fn = this.inner[name];
    if (typeof fn === 'function') {
      // This is right pain point!!
      // TS2556: A spread argument must either have a tuple type or be passed to a rest parameter.
      fn(...args);
    }
  }
}

Partea fn(...args) continuă să afișeze eroare ca mai sus. Cred că args ar trebui să fie dedus ca tuplu deoarece îi permitem compilatorului să știe că tipul lui args va fi extins de Parameter<Inner[F]>. Cum pot să repar asta?

const outer = new Outer().proxy;
// IDE can infer parameter's type from second parameter
outer('method1', 'stringArg');
outer('method2', 1, 2);

Un alt punct dureros este că IDE-ul poate deduce tipurile de parametri în funcție de primul argument. (Captura reală a IDE-ului este atașată mai jos)

Mulțumesc anticipat pentru răspunsul tău! :)