Я хочу добавить метод к методу:
class MyClass {
public foo(text: string): string {
return text + ' FOO!'
}
// Some magical code which adds the method `bar` to `foo`.
}
const obj = new MyClass();
console.info(obj.foo('thing'));
console.info(obj.foo.bar('other thing'));
Это возможно? Я нашел аналогичный случай для функций:
function Sum(x: number) { /*...*/ }
namespace Sum {
export function empty() { /*...*/ }
}
Есть ли способ сделать то же самое с методами класса?
Я бы хотел, чтобы код в классе не обновлялся после создания объекта.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Не совсем то, о чем вы просите, но конечный результат работает:
class MyClass {
public foo: MyChildClass = new MyChildClass();
}
class MyChildClass {
public bar(text: string): string{
return text;
}
}
const obj = new MyClass();
console.info(obj.foo.bar('thing'));
РЕДАКТИРОВАТЬ Прочитал ваш ответ на свой комментарий. Я думаю, что более простой способ достичь вашей цели - использовать такие параметры по умолчанию, как:
function foo(text: string, snapshot = false): string{
if (snapshot){
return 'snapshot';
}
return text;
}
console.debug(foo('test'));
console.debug(foo('test', true));
Теперь ваше решение имеет то преимущество, что вы можете видеть на сайте вызова, что вы запрашиваете обход или снимок, явно из-за дополнительных имен функций. Вы можете добиться аналогичного результата в машинописном тексте, заменив аргументы foo интерфейсом с необязательными свойствами. На других языках мы бы назвали эту технику параметрами:
interface iFooArgs{
text: string;
bypass?: boolean;
snapshot?: boolean;
}
function foo(args: iFooArgs): string {
if (args.bypass){
return 'bypass';
}
if (args.snapshot){
return 'snapshot';
}
return args.text;
}
console.debug(foo({text: 'test'}));
console.debug(foo({text: 'bypass?', bypass: true}));
console.debug(foo({text: 'snapshot?', snapshot: true}));
@ AndréC.Andersen Это интересно. Я думаю, что в js это обычно делается просто так, чтобы foo включал параметр для обхода кеша. Потребители foo, которые не предоставляют параметр «bypass cache», получат кеш. foo () сама проверит, были ли предоставлены параметры, или "undefined" по умолчанию для вашего "использования по умолчанию".
@ AndréC.Andersen Добавил к моему ответу то, что я считаю более простым решением вашей проблемы.
Вы можете получить доступ к функции в прототипе классов и делать с ней все, что захотите. Не думаю, что это особенно красиво, но вы можете сделать что-то вроде этого:
class MyClass {
constructor(myName) {
this.myName = myName
this.constructor.prototype.foo.bar = (function(a) {
console.info(this.myName, "calling foo.bar with:", a)
}).bind(this)
}
foo(text) {
return text + ' FOO!'
}
}
const obj = new MyClass("Mark");
obj.foo.bar('thing')
console.info(obj.foo('test'))Обновлено: Это можно решить чисто с помощью типы пересечений:
class MyClass {
constructor() {
this.foo = function () {
return "this is a"
};
this.foo.bar = function() {
return "this is b"
};
}
public foo: Function & { bar?: () => string };
}
const obj = new MyClass();
console.info(obj.foo());
console.info(obj.foo.bar());
Протестируйте его в игровой группе Typescript
Это возможно, потому что при использовании знака & в определении типа метода класса мы являемся возня вместе как типом Function, так и простым типом объекта, который имеет 1 свойство bar, которое является другой функцией. Однако это свойство должно быть объявлено как необязательное во втором типе, потому что Typescript будет жаловаться на то, что в первом назначении внутри конструктора класса он не удовлетворяет этому дополнительному типу. Но на самом деле следующее выражение в конструкторе завершает его, присваивая свойство bar функции foo.
--- СТАРЫЙ ответ следует, не используйте его, он не делает именно то, что хотел OP
Вместо метода определите метод доступа геттера для члена класса 'foo', который возвращает объект с функцией 'bar'.
class MyClass {
get foo(): {bar: (text: string) => string} {
// run any code here that needs to be run before bar()
return {
bar: (text: string) => {
return text + ' FOO!';
}
}
}
}
const obj = new MyClass();
console.info(obj.foo.bar('thing'));
Похоже, что foo() больше не является вызываемой функцией. Есть ли способ сделать что-то подобное, но при этом позволить obj.foo() работать?
foo- это метод - это основа того, чего я хочу достичь. Я хочу, чтобы методfoo()использовался по умолчанию. Это может быть метод доступа к дорогостоящим ресурсам со встроенным кешированием. Вам может понравиться альтернативный способ использования этого метода, например, обход или аннулирование кеша. Возможно, вы обычно используетеobj.fetch('42'), но иногда вам может понадобитьсяobj.fetch.bypass('42')для принудительной загрузки дорогостоящих ресурсов илиobj.fetch.snapshot('42')для принудительного использования кеша, даже если тайм-аут кеша истек. В python я бы просто использовал ваш пример с__call__(self).