Я новичок в 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, имеет подпись вызова, я думаю? Я думаю, что я неправильно понимаю что-то важное о типизации функций, но я не знаю, что это такое.
Спасибо!
Возвращаемая функция имеет сигнатуру вызова, но вы сказали Typescript полностью игнорировать это, добавив : any
в свою подпись.
Не делай этого.
public toggleBody: boolean;
для public toggleBody: any;
оно работает.
"Невозможно вызвать выражение, тип которого не имеет сигнатуры вызова."
В вашем коде:
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);
Я думаю, что вы хотите:
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
уважать ту же подпись.
Давайте разберемся с этим:
Ошибка говорит
Невозможно вызвать выражение, тип которого не имеет подписи вызова.
Код:
Проблема в этой строке public toggleBody: string;
&
Это отношение к этим строкам:
...
return this.toggleBody(true);
...
return this.toggleBody(false);
Вы говорите, что 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) не имеет подписи вызова (имеет строковую подпись.)
Это всего лишь пример ошибки, но в несколько ином контексте, где ничего не возвращалось, и машинописный код ожидал объект, похожий на обещание.
Используя машинопись и реагирование, ошибка произошла для меня с:
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()
togglrBody
не должен быть строкой, так как вы хотите, чтобы она была функцией