Błąd: nie można wywołać wyrażenia, którego typ nie ma podpisu połączenia


121

Jestem zupełnie nowy w maszynopisie i mam dwie klasy. W klasie rodzicielskiej mam:

abstract class Component {
  public deps: any = {};
  public props: any = {};

  public setProp(prop: string): any {
    return <T>(val: T): T => {
      this.props[prop] = val;
      return val;
    };
  }
}

W klasie dziecięcej mam:

class Post extends Component {
  public toggleBody: string;

  constructor() {
    this.toggleBody = this.setProp('showFullBody');
  }

  public showMore(): boolean {
    return this.toggleBody(true);
  }

  public showLess(): boolean {
    return this.toggleBody(false);
  }
}

Zarówno showMore, jak i ShowLess wyświetlają błąd „Nie można wywołać wyrażenia, którego typ nie ma sygnatury wywołania”.

Ale myślę, że funkcja, którą zwraca setProp, CZY ma sygnaturę wywołania? Myślę, że źle rozumiem coś ważnego w typowaniu funkcji, ale nie wiem, co to jest.

Dzięki!


1
togglrBodynie powinien być łańcuchem, ponieważ chcesz, aby był to funkcja
eavidan

1
@eavidan tak, jest to funkcja, która w rzeczywistości zwraca wartość logiczną. Początkowo myślałem, że zwróci ciąg. Więc na co mam to zmienić?
Justin

Cokolwiek setProp zwraca, co wydaje się wyglądać<T>(val: T) => T
eavidan

Odpowiedzi:


76

Funkcja, którą zwraca, ma sygnaturę wywołania, ale powiedziałeś Typescriptowi, aby całkowicie to zignorował, dodając : anyjego podpis.

Nie rób tego.


OK postęp, dzięki! Teraz pojawia się „błąd TS2322: Wpisz„ <T> (val: T) => T ”nie można przypisać do typu„ boolean ”." Jeśli usunę: any. Myślę, że dlatego dodałem: na pierwszym miejscu. Właściwie nadal otrzymuję oryginalne błędy.
Justin

1
Jeśli mogę to zrobić i zmiany public toggleBody: boolean;do public toggleBody: any;to działa.
Justin

1
@Justin, dlaczego spodziewałeś się czegoś innego? Roszczenie this.toggleBodypowinno zostać zwrócone boolean, ale nie jest to zgodne z wartością zwracaną setProp, którą mu przypisałeś. Wydaje się, że po prostu losowo wrzucasz typy, nie myśląc o tym, co tak naprawdę chcesz wysłać, a co zwrócić.
jonrsharpe

@jonrsharpe Ok tak, to ma sens. W tym przypadku zwraca wartość logiczną, ale generalnie zwraca dowolną. Więc muszę użyć dowolnego?
Justin

9
Ta odpowiedź przyniosłaby korzyści, gdyby wyjaśniono, jak należy postępować, na przykładzie.
Andre M

38

„Nie można wywołać wyrażenia, którego typ nie ma podpisu wywołania”.

W swoim kodzie:

class Post extends Component {
  public toggleBody: string;

  constructor() {
    this.toggleBody = this.setProp('showFullBody');
  }

  public showMore(): boolean {
    return this.toggleBody(true);
  }

  public showLess(): boolean {
    return this.toggleBody(false);
  }
}

Masz public toggleBody: string;. Nie możesz wywołać funkcji a stringjako funkcji. Stąd błędy na: this.toggleBody(true);ithis.toggleBody(false);


28

Rozbijmy to:

  1. Błąd mówi

    Nie można wywołać wyrażenia, którego typ nie ma podpisu wywołania.

  2. Kod:

Problem tkwi w tej linii public toggleBody: string;i

jest to związek z tymi liniami:

...
return this.toggleBody(true);
...
return this.toggleBody(false);
  1. Wynik:

Twoje powiedzenie toggleBodyjest a, stringale wtedy traktujesz je jak coś, co ma call signature(tj. Strukturę czegoś, co można nazwać: lambdy, proc, funkcje, metody, itd.). Musisz zmienić deklarację napublic toggleBody: (arg: boolean) => boolean; .

Dodatkowe szczegóły:

„Wywołaj” oznacza wywołanie lub zastosowanie funkcji.

„Wyrażenie” w JavaScript jest w zasadzie czymś, co generuje wartość, więc this.toggleBody() liczy się jako wyrażenie.

W tym wierszu zadeklarowano „typ” public toggleBody: string

„Brak sygnatury wywołania” this.toggleBody()dzieje się tak, ponieważ próbujesz wywołać coś , co nie ma sygnatury (tj. strukturę czegoś, co można nazwać: lambdy, proc, funkcje, metody itp.), co można wywołać. Powiedziałeś, że this.toggleBodyto coś, co działa jak sznurek.

Innymi słowy, błąd mówi

Nie można wywołać wyrażenia (this.toggleBody), ponieważ jego typ (: string) nie ma podpisu wywołania (bc ma podpis w postaci ciągu).


4
To jedna z najlepszych odpowiedzi na świecie! Znam wszystkie te definicje, ale kiedy zobaczyłem ostrzeżenie, wszystkie te terminy, w jednym gęstym zdaniu, były za dużo dla mojego zagraconego mózgu.
cham

6

Myślę, że chcesz:

abstract class Component {
  public deps: any = {};
  public props: any = {};

  public makePropSetter<T>(prop: string): (val: T) => T {
    return function(val) {
      this.props[prop] = val
      return val
    }
  }
}

class Post extends Component {
  public toggleBody: (val: boolean) => boolean;

  constructor () {
    super()
    this.toggleBody = this.makePropSetter<boolean>('showFullBody')
  }

  showMore (): boolean {
    return this.toggleBody(true)
  }

  showLess (): boolean {
    return this.toggleBody(false)
  }
}

Nadeszła ważna zmiana setProp (tj makePropSetter. Nowego kodu). To, co naprawdę robisz, to powiedzenie: jest to funkcja, której podana jest nazwa właściwości, zwróci funkcję, która umożliwia zmianę tej właściwości.

Opcja <T>on makePropSetterumożliwia zablokowanie tej funkcji w określonym typie. Konstruktor <boolean>w podklasie jest w rzeczywistości opcjonalny. Ponieważ przydzielasz dotoggleBody , a typ jest już w pełni określony, kompilator TS będzie mógł go samodzielnie rozwiązać.

Następnie w swojej podklasie wywołujesz tę funkcję, a typ zwracany jest teraz właściwie rozumiany jako funkcja z określonym podpisem. Oczywiście musisz toggleBodyuszanować ten sam podpis.


5

Oznacza to, że próbujesz wywołać coś, co nie jest funkcją

const foo = 'string'
foo() // error

0

Dodaj typ do zmiennej, a następnie zwróć.

Na przykład:

const myVariable : string [] = ['hello', 'there'];

const result = myVaraible.map(x=> {
  return
  {
    x.id
  }
});

=> Ważną częścią jest dodanie ciągu [] typ itp:


0

Miałem ten sam komunikat o błędzie. W moim przypadku nieumyślnie pomieszałem export default function myFuncskładnię ES6 zconst myFunc = require('./myFunc'); .

Użycie module.exports = myFunc;zamiast tego rozwiązało problem.


0

Ten błąd może być spowodowany, gdy żądasz od czegoś wartości i umieszczasz nawias na końcu, tak jakby to było wywołanie funkcji, ale wartość jest poprawnie pobierana bez kończenia nawiasu. Na przykład, jeśli uzyskujesz dostęp do Property „get” w Typescript.

private IMadeAMistakeHere(): void {
    let mynumber = this.SuperCoolNumber();
}

private IDidItCorrectly(): void {
    let mynumber = this.SuperCoolNumber;
}

private get SuperCoolNumber(): number {
    let response = 42;
    return response;
};
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.