Это следует считать ошибкой в TypeScript, учитывая, что один и тот же код в JS ведет себя по-разному?
Да, это определенно похоже на ошибку, связанную с передачей Typescript синтаксис распространения объекта. Скомпилированный TS не делает то же самое, что и JS.
. В первом случае вы определяете объект y
со свойством x2
, которое является геттером:
var y = {
...x,
_originalX2:x.x2,
get x2(){
Таким образом, ссылка на y.x2
позже приводит к вызову геттера. Но в скомпилированном Typescript мы получаем:
var x = { x1: 5, x2: 7 };
var y = Object.assign(
Object.assign({}, x),
{
_originalX2: x.x2,
get x2() {
console.log(this.x1);
}
}
);
Это приведет к немедленному вызову геттера - геттеры будут вызваны, когда в объекте передан второй или более аргумент внутри Object.assign
. И когда вызывается геттер, this
ссылается на второй аргумент, этот объект здесь:
{
_originalX2: x.x2,
get x2() {
console.log(this.x1);
}
}
, который не имеет свойства x1
, поэтому он регистрирует undefined
.
undefined
регистрируется до того, как завершится Object.assign
, прежде чем вы перейдете к следующей строке console.log(y.x2);
.
. Для более минимального примера:
var y = {
...{},
get prop(){
console.log('should not be invoked immediately');
}
};
некорректно переносится в
var y = Object.assign({}, { get prop() {
console.log('should not be invoked immediately');
} });
Если вы сделаете так, чтобы Typescript не не передавал синтаксис распространения объекта, при увеличении цели после ES2017 это сработает. Например, с ESNext вышеупомянутое передается к:
var y = {
...{},
get prop() {
console.log('should not be invoked immediately');
}
};