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


121

Я новичок в машинописи, и у меня два класса. В родительском классе у меня есть:

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не должно быть строкой, так как вы хотите, чтобы это была функция
Ивидан

1
@eavidan да, это функция, которая фактически возвращает логическое значение. Первоначально я думал, что он вернет строку. Так на что мне его поменять?
Джастин

Независимо от того, что вернется setProp, это похоже<T>(val: T) => T
Эвидан

Ответы:


76

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

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


Хорошо, прогресс, спасибо! Теперь я получаю «ошибку TS2322: Тип« <T> (val: T) => T »не может быть назначен типу« логическое »». Если я удалю: 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;. Вы не можете вызвать a 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относитесь к нему как к чему-то, что имеет (т.е. структуру чего-то, что может быть вызвано: лямбды, процедуры, функции, методы и т. Д. В JS просто функция tho.). Вам нужно изменить декларацию на public toggleBody: (arg: boolean) => boolean;.

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

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

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

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

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

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

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


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

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

=> Важной частью является добавление типа string [] и т. Д.:


0

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

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


0

Эта ошибка может быть вызвана тем, что вы запрашиваете значение у чего-либо и ставите скобки в конце, как если бы это был вызов функции, но при этом значение извлекается правильно без закрывающих скобок. Например, если вы обращаетесь к свойству "получить" в Typescript.

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

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

private get SuperCoolNumber(): number {
    let response = 42;
    return response;
};
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.