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

57

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

Спасибо!

  • 1
    togglrBody не должен быть строкой, так как вы хотите, чтобы она была функцией
  • 1
    @eavidan да, это функция, которая на самом деле возвращает логическое значение. Я изначально думал, что это вернет строку. Так что я могу изменить это?
Показать ещё 1 комментарий
Теги:
types

5 ответов

32
Лучший ответ

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

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

  • 0
    Хорошо, прогресс, спасибо! Теперь я получаю «ошибка TS2322: тип« <T> (val: T) => T »не может быть назначен типу« логический »). Если я удалю: любой. Я думаю, что именно поэтому я добавил: любой в первую очередь. Я на самом деле все еще получаю оригинальные ошибки, а также.
  • 0
    Если я сделаю это и public toggleBody: boolean; для public toggleBody: any; оно работает.
Показать ещё 6 комментариев
21

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

В вашем коде:

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

5

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

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 уважать ту же подпись.

1

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

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

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

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

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

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

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

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

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

  • 0
    Это один из лучших ответов, когда-либо! Я знаю все эти определения, но когда я увидел предупреждающее сообщение, все эти термины в одном плотном предложении оказались слишком сложными для моего загроможденного мозга.
0

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

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню