ข้อผิดพลาด: ไม่สามารถเรียกใช้นิพจน์ที่ไม่มีลายเซ็นการโทร


121

ฉันใหม่เอี่ยมสำหรับ typescript และฉันมีสองคลาส ในคลาสผู้ปกครองฉันมี:

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

ในชั้นเด็กฉันมี:

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

ทั้ง showMore และ ShowLess ให้ข้อผิดพลาด "ไม่สามารถเรียกใช้นิพจน์ที่ไม่มีลายเซ็นการโทร"

แต่ฟังก์ชันที่ setProp ส่งกลับมีลายเซ็นการโทรหรือไม่? ฉันคิดว่าฉันเข้าใจผิดบางอย่างที่สำคัญเกี่ยวกับการพิมพ์ฟังก์ชัน แต่ฉันไม่รู้ว่ามันคืออะไร

ขอบคุณ!


1
togglrBodyไม่ควรเป็นสตริงเนื่องจากคุณต้องการให้เป็นฟังก์ชัน
eavidan

1
@eavidan ใช่มันเป็นฟังก์ชั่นที่คืนค่าบูลีน เดิมทีฉันคิดว่ามันจะส่งคืนสตริง แล้วฉันจะเปลี่ยนเป็นอะไร?
จัสติน

ไม่ว่า setProp จะส่งคืนซึ่งดูเหมือนว่า<T>(val: T) => T
eavidan

คำตอบ:


76

ฟังก์ชันที่ส่งคืนมีลายเซ็นการโทร แต่คุณบอกว่า typescript ให้ละเว้นสิ่งนั้นโดยการเพิ่ม: anyลายเซ็น

อย่าทำอย่างนั้น


ความคืบหน้าขอบคุณ! ตอนนี้ฉันได้รับ "error TS2322: Type '<T> (val: T) => T' ไม่สามารถกำหนดให้พิมพ์ 'boolean' ได้" ถ้าฉันลบ: any. ฉันคิดว่านี่คือเหตุผลที่ฉันเพิ่ม: ใด ๆ ในตอนแรก ฉันยังคงได้รับข้อผิดพลาดเดิมเช่นกัน
จัสติน

1
ถ้าผมทำเช่นนี้และการเปลี่ยนแปลงpublic toggleBody: boolean;ที่จะpublic toggleBody: any;มันทำงาน
จัสติน

1
@ จัสตินทำไมคุณถึงคาดหวังอย่างอื่น? คุณthis.toggleBodyควรส่งคืนbooleanแต่ไม่สอดคล้องกับมูลค่าคืนsetPropที่คุณกำหนดให้ ดูเหมือนคุณจะสุ่มสุ่มเลือกประเภทโดยไม่ได้คิดถึงสิ่งที่คุณต้องการส่งและคืน
jonrsharpe

@jonrsharpe ตกลงใช่มันสมเหตุสมผล ในกรณีนี้จะส่งคืนบูลีน แต่โดยทั่วไปจะส่งคืนค่าใด ๆ ฉันต้องใช้อะไรบ้าง?
จัสติน

9
คำตอบนี้จะได้รับประโยชน์จากการอธิบายวิธีการทำสิ่งต่างๆที่ถูกต้องพร้อมตัวอย่าง
Andre M

38

"ไม่สามารถเรียกใช้นิพจน์ที่ไม่มีลายเซ็นการโทร"

ในรหัสของคุณ:

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

public toggleBody: string;คุณมี คุณไม่สามารถเรียกใช้stringเป็นฟังก์ชันได้ ดังนั้นข้อผิดพลาดใน: this.toggleBody(true);และthis.toggleBody(false);


28

มาทำลายสิ่งนี้:

  1. ข้อผิดพลาดแจ้งว่า

    ไม่สามารถเรียกใช้นิพจน์ที่ไม่มีลายเซ็นการโทร

  2. รหัส:

ปัญหาอยู่ในบรรทัดนี้public toggleBody: string;&

มันสัมพันธ์กับบรรทัดเหล่านี้:

...
return this.toggleBody(true);
...
return this.toggleBody(false);
  1. ผลลัพธ์:

คำพูดของคุณtoggleBodyเป็นstringแต่การปฏิบัติของคุณเหมือนบางสิ่งที่มีcall signature(เช่นโครงสร้างของสิ่งที่สามารถเรียกได้: lambdas, proc, ฟังก์ชั่น, วิธีการ ฯลฯ ใน JS just function tho) public toggleBody: (arg: boolean) => boolean;คุณจำเป็นต้องเปลี่ยนการประกาศให้เป็น

รายละเอียดเพิ่มเติม:

"เรียกใช้" หมายถึงการโทรของคุณหรือการใช้ฟังก์ชัน

"นิพจน์" ใน Javascript นั้นโดยพื้นฐานแล้วเป็นสิ่งที่สร้างค่าดังนั้นจึงthis.toggleBody()นับเป็นนิพจน์

"type" ถูกประกาศในบรรทัดนี้ public toggleBody: string

"ไม่มีลายเซ็นการโทร" เนื่องจากคุณพยายามเรียกสิ่งthis.toggleBody()ที่ไม่มีลายเซ็น (เช่นโครงสร้างของสิ่งที่สามารถเรียกได้: lambdas, proc, ฟังก์ชัน, วิธีการ ฯลฯ ) ที่สามารถเรียกได้ คุณบอกว่าthis.toggleBodyเป็นสิ่งที่ทำหน้าที่เหมือนสตริง

กล่าวอีกนัยหนึ่งคือข้อผิดพลาดกำลังพูด

ไม่สามารถเรียกนิพจน์ (this.toggleBody) ได้เนื่องจากประเภท (: string) ไม่มีลายเซ็นการโทร (bc มีลายเซ็นสตริง)


4
นี่คือหนึ่งในคำตอบที่ดีที่สุดเลยทีเดียว! ฉันรู้คำจำกัดความเหล่านั้นทั้งหมด แต่เมื่อฉันเห็นข้อความเตือนคำศัพท์เหล่านั้นทั้งหมดในประโยคที่หนาแน่นเพียงประโยคเดียวมันมากเกินไปสำหรับสมองที่รกของฉัน
จาม

6

ฉันคิดว่าสิ่งที่คุณต้องการคือ:

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

การเปลี่ยนแปลงที่สำคัญอยู่ในsetProp(กล่าวคือmakePropSetterในรหัสใหม่) สิ่งที่คุณกำลังทำจริงๆคือการพูด: นี่คือฟังก์ชันที่มาพร้อมกับชื่อคุณสมบัติจะส่งคืนฟังก์ชันที่อนุญาตให้คุณเปลี่ยนคุณสมบัตินั้น

<T>บนmakePropSetterช่วยให้คุณสามารถล็อคฟังก์ชั่นที่อยู่ในประเภทที่เฉพาะเจาะจง ตัวสร้าง<boolean>ในคลาสย่อยเป็นทางเลือกที่แท้จริง เนื่องจากคุณกำลังกำหนดให้toggleBodyและมีประเภทที่ระบุไว้ครบถ้วนแล้วคอมไพเลอร์ TS จะสามารถทำงานได้ด้วยตัวเอง

จากนั้นในคลาสย่อยของคุณคุณเรียกใช้ฟังก์ชันนั้นและตอนนี้ประเภทการส่งคืนได้รับการเข้าใจอย่างถูกต้องว่าเป็นฟังก์ชันที่มีลายเซ็นเฉพาะ โดยปกติคุณจะต้องtoggleBodyเคารพลายเซ็นเดียวกันนั้น


5

หมายความว่าคุณกำลังพยายามเรียกสิ่งที่ไม่ใช่ฟังก์ชัน

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

0

เพิ่มประเภทให้กับตัวแปรของคุณแล้วส่งคืน

เช่น:

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

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

=> ส่วนที่สำคัญคือการเพิ่มสตริง [] ชนิด ฯลฯ :


0

ฉันมีข้อความแสดงข้อผิดพลาดเดียวกัน ในกรณีของฉันฉันผสมexport default function myFuncไวยากรณ์ES6 โดยไม่ได้ตั้งใจกับconst myFunc = require('./myFunc');.

การใช้module.exports = myFunc;แทนช่วยแก้ปัญหาได้


0

ข้อผิดพลาดนี้อาจเกิดขึ้นได้เมื่อคุณร้องขอค่าจากบางสิ่งบางอย่างและคุณใส่วงเล็บต่อท้ายราวกับว่าเป็นการเรียกฟังก์ชัน แต่ค่าจะถูกดึงออกมาอย่างถูกต้องโดยไม่ต้องใส่วงเล็บ ตัวอย่างเช่นหากสิ่งที่คุณกำลังเข้าถึงคือ Property 'get' ใน typescript

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

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

private get SuperCoolNumber(): number {
    let response = 42;
    return response;
};
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.