Подтвердить что ты не робот

Ошибка: не может вызывать выражение, тип которого не имеет сигнатуры вызова

Я новичок в 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 возвращает DOES, имеет подпись вызова, я думаю? Я думаю, что я неправильно понимаю что-то важное о типизации функций, но я не знаю, что это такое.

Спасибо!

4b9b3361

Ответ 1

Возвращаемая функция имеет сигнатуру вызова, но вы сказали Typescript полностью игнорировать это, добавив : any в свою подпись.

Не делай этого.

Ответ 2

"Невозможно вызвать выражение, тип которого не имеет сигнатуры вызова."

В вашем коде:

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

Ответ 3

Давайте разберемся с этим:

  1. Ошибка говорит

    Невозможно вызвать выражение, тип которого не имеет подписи вызова.

  2. Код:

Проблема в этой строке public toggleBody: string; &

Это отношение к этим строкам:

...
return this.toggleBody(true);
...
return this.toggleBody(false);
  1. Результат:

Ваше высказывание toggleBody - это string но затем вы рассматриваете ее как нечто, имеющее call signature (т.е. Структуру чего-то, что может быть вызвано: лямбда-выражения, proc, функции, методы и т.д. В JS просто функция tho.). Вам нужно изменить объявление на public toggleBody: (arg: boolean) => boolean; ,

Дополнительные детали:

"вызвать" означает ваш вызов или применение функции.

"Выражение" в Javascript - это то, что создает значение, поэтому this.toggleBody() считается выражением.

"тип" объявлен в этой строке public toggleBody: string

"отсутствует подпись вызова" это происходит потому, что вы пытаетесь вызвать что-то this.toggleBody(), у которого нет подписи (то есть структура чего-то, что может быть вызвано: лямбда-выражения, процедуры, функции, методы и т.д.), которые могут быть называется. Вы сказали, что this.toggleBody действует как строка.

Другими словами, ошибка говорит

Невозможно вызвать выражение (this.toggleBody), поскольку у его типа (: string) отсутствует подпись вызова (bc имеет строковую подпись.)

Ответ 4

Я думаю, что вы хотите:

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

Ответ 6

Это всего лишь пример ошибки, но в несколько ином контексте, где ничего не возвращалось, и машинописный код ожидал объект, похожий на обещание.

Используя машинопись и реагирование, ошибка произошла для меня с:

let thing = SomePromise.then(Promise.resolve)
    .catch(e => { 
        this.setState(e)
        // not returning anything here 
    })
// thing.then().catch()

Мне нужно было вернуть объект обещания:

let thing = SomePromise.then(Promise.resolve)
    .catch(Promise.reject)
// thing.then().catch()

Ответ 7

Добавьте тип в вашу переменную и затем вернитесь.

Например:

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

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

=> Важной частью является добавление строки [] и т.д.

Ответ 8

У меня было то же сообщение об ошибке. В моем случае я случайно смешал синтаксис ES6 export default function myFunc с const myFunc = require('./myFunc');.

Использование module.exports = myFunc; вместо этого решило проблему.

Ответ 9

Эта ошибка может быть вызвана тем, что вы запрашиваете значение у чего-либо и ставите круглые скобки в конце, как если бы это был вызов функции, но значение корректно извлекается без использования круглых скобок. Например, если то, к чему вы обращаетесь, это свойство '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;
};