Kesalahan: Tidak dapat memanggil ekspresi yang tipenya tidak memiliki tanda tangan panggilan

121

Saya baru mengenal ketikan, dan saya memiliki dua kelas. Di kelas orang tua saya memiliki:

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;
    };
  }
}

Di kelas anak saya memiliki:

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);
  }
}

Baik showMore dan ShowLess memberi saya kesalahan, "Tidak dapat memanggil ekspresi yang tipenya tidak memiliki tanda tangan panggilan."

Tetapi fungsi yang dikembalikan setProp APAKAH memiliki tanda tangan panggilan, menurut saya? Saya pikir saya salah paham tentang sesuatu yang penting tentang pengetikan fungsi, tetapi saya tidak tahu apa itu.

Terima kasih!

Justin
sumber
1
togglrBodytidak boleh berupa string, karena Anda menginginkannya menjadi fungsi
eavidan
1
@eavidan ya itu adalah fungsi yang benar-benar mengembalikan boolean. Saya awalnya berpikir itu akan mengembalikan string. Jadi apa yang harus saya ubah?
Justin
Apa pun yang dikembalikan setProp, yang nampaknya<T>(val: T) => T
eavidan

Jawaban:

76

Fungsi yang dikembalikannya memiliki tanda tangan panggilan, tapi Anda memberi tahu Ketikan untuk mengabaikannya sepenuhnya dengan menambahkan : anytanda tangannya.

Jangan lakukan itu.

SLaks
sumber
Ok kemajuan, Terima kasih! Sekarang saya mendapatkan "error TS2322: Type '<T> (val: T) => T' is not assignable to type 'boolean'." Jika saya menghapus: ada. Saya pikir inilah mengapa saya menambahkan: apapun di tempat pertama. Saya sebenarnya masih mendapatkan kesalahan asli juga.
Justin
1
Jika saya melakukan ini dan perubahan public toggleBody: boolean;untuk public toggleBody: any;bekerja.
Justin
1
@Justin mengapa Anda mengharapkan hal lain? Anda mengklaim this.toggleBodyharus mengembalikan boolean, tapi itu tidak konsisten dengan nilai pengembalian setPropyang Anda tetapkan padanya. Anda tampaknya hanya memasukkan huruf secara acak tanpa memikirkan tentang apa yang sebenarnya ingin Anda kirim dan kembalikan.
jonrsharpe
@jonrsharpe Ok ya itu masuk akal. Dalam hal ini ia mengembalikan boolean, tetapi secara umum ia mengembalikan apapun. Jadi saya harus menggunakan apapun?
Justin
9
Tanggapan ini akan mendapat manfaat dari menjelaskan cara yang benar untuk melakukan sesuatu, dengan sebuah contoh.
Andre M
38

"Tidak dapat memanggil ekspresi yang tipenya tidak memiliki tanda tangan panggilan."

Dalam kode Anda:

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);
  }
}

Anda punya public toggleBody: string;. Anda tidak dapat memanggil stringsebagai fungsi. Karenanya kesalahan pada: this.toggleBody(true);danthis.toggleBody(false);

basarat
sumber
28

Mari kita uraikan ini:

  1. Kesalahan mengatakan

    Tidak dapat memanggil ekspresi yang tipenya tidak memiliki tanda tangan panggilan.

  2. Kode:

Masalahnya ada di baris ini public toggleBody: string;&

itu terkait dengan baris ini:

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

Pepatah Anda toggleBodyadalah a stringtetapi kemudian Anda memperlakukannya seperti sesuatu yang memiliki call signature(yaitu struktur dari sesuatu yang dapat disebut: lambda, proc, functions, methods, dll. Dalam JS hanya berfungsi tho.). Anda perlu mengubah deklarasi menjadi public toggleBody: (arg: boolean) => boolean;.

Detail Ekstra:

"memanggil" berarti Anda memanggil atau menerapkan suatu fungsi.

"ekspresi" dalam Javascript pada dasarnya adalah sesuatu yang menghasilkan nilai, jadi this.toggleBody()dihitung sebagai ekspresi.

"type" dideklarasikan di baris ini public toggleBody: string

"kekurangan tanda tangan panggilan" ini karena Anda mencoba memanggil sesuatu this.toggleBody()yang tidak memiliki tanda tangan (yaitu struktur dari sesuatu yang dapat disebut: lambda, proc, fungsi, metode, dll.) yang dapat dipanggil. Anda mengatakan this.toggleBodysesuatu yang bertindak seperti tali.

Dengan kata lain kesalahan mengatakan

Tidak dapat memanggil ekspresi (this.toggleBody) karena tipenya (: string) tidak memiliki tanda tangan panggilan (karena memiliki tanda tangan string.)

Taysky
sumber
4
Ini adalah salah satu jawaban terbaik! Saya tahu semua definisi itu tetapi ketika saya melihat pesan peringatan, semua istilah itu, dalam satu kalimat padat, terlalu banyak untuk otak saya yang berantakan.
cham
6

Saya pikir yang Anda inginkan adalah:

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)
  }
}

Perubahan penting ada di setProp(yaitu, makePropSetterdalam kode baru). Apa yang sebenarnya Anda lakukan di sana adalah mengatakan: ini adalah fungsi, yang disediakan dengan nama properti, akan mengembalikan fungsi yang memungkinkan Anda mengubah properti itu.

The <T>on makePropSettermemungkinkan Anda untuk mengunci fungsi yang ke jenis tertentu. The <boolean>dalam konstruktor subclass ini sebenarnya opsional. Karena Anda sedang menugaskan ke toggleBody, dan itu sudah memiliki tipe yang ditentukan sepenuhnya, kompiler TS akan dapat mengerjakannya sendiri.

Kemudian, di subclass Anda, Anda memanggil fungsi itu, dan tipe kembalian sekarang dipahami dengan benar sebagai fungsi dengan tanda tangan tertentu. Tentu, Anda harus toggleBodymenghormati tanda tangan yang sama itu.

Andrew Miner
sumber
5

Artinya Anda mencoba memanggil sesuatu yang bukan fungsi

const foo = 'string'
foo() // error
Gunar Gessner
sumber
0

Tambahkan tipe ke variabel Anda dan kemudian kembali.

Misalnya:

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

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

=> Bagian penting adalah menambahkan string [] type dll:

Afshin Ghazi
sumber
0

Saya mendapat pesan kesalahan yang sama. Dalam kasus saya, saya secara tidak sengaja mencampur export default function myFuncsintaks ES6 denganconst myFunc = require('./myFunc'); .

Menggunakan module.exports = myFunc;malah memecahkan masalah.

Charlie Weems
sumber
0

Kesalahan ini dapat terjadi saat Anda meminta nilai dari sesuatu dan Anda meletakkan tanda kurung di akhir, seolah-olah itu adalah panggilan fungsi, namun nilainya diambil dengan benar tanpa mengakhiri tanda kurung. Misalnya, jika yang Anda akses adalah Properti 'dapatkan' di Skrip Ketik.

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

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

private get SuperCoolNumber(): number {
    let response = 42;
    return response;
};
StackOverflowUser
sumber