Технически, это TypeScript, но проблема в JS.
У меня есть интерфейс с именем Animal
, например:
interface Animal {
name: string;
speak(): void;
}
function animal(name: string): Animal {
return {
name,
speak() {
console.log('This animal does not know how to speak!');
},
};
}
У меня есть другой интерфейс,Dog
, который расширяет Animal
и имеет сопутствующую функцию, которая расширяет обычный объект и делает его Dog
.
interface Dog extends Animal {
breed: string;
}
function dog<T extends Animal>(animal: T, breed: string): T & Dog {
const obj = {
breed,
...animal,
speak() {
console.log(`${obj.name} says Woof!`);
},
};
return obj;
}
У меня также есть другой интерфейс под названием Competition
, чтобы представлять всех животныхкоторые участвуют в конкурсе.Это не ограничено собаками.
interface Competition extends Animal {
prize: number;
}
function competition<T extends Animal>(animal: T, prize: number): T & Competition {
return {
prize,
...animal,
};
}
Пока все хорошо.Но теперь мне нужен Map
, в котором хранится животное, а также имя его владельца (при условии, что один человек может владеть только одним животным).
const map: Map<string, Animal> = new Map();
Теперь есть парень по имени Джон, и онимеет сибирского хаски по имени Foo.
map.set('John', dog(animal('Foo'), 'Siberian Husky'));
Джон заставляет Foo присоединиться к соревнованию, и Foo занимает второе место.
map.set('John', competition(map.get('John'), 2));
Однако, на соревновании Джон видит, что другая собакатакже называется Foo, и поэтому решает переименовать его собаку.
map.get('John').name = 'Timmy';
map.get('John').speak(); // Foo says Woof!
Проблема в том, что speak
обращается к name
объекта, который находится в закрытии во время моего вызова dog(...)
, в данном случае "Foo"
.Изменение значения переменных в объекте не приводит к изменению значения в замыкании.
Мой вопрос: как мне также изменить значение в замыкании?Кажется, я не могу придумать способ, который не требует серьезных изменений в моей нынешней системе.
Детская площадка