Загрузка…
Загрузка…
Один intent — два мира. Legacy мутирует descriptor in-place:
// Same intent, both worlds. Legacy mutates the descriptor in place:
class ApiLegacy {
@logged // experimentalDecorators: true
fetch(id: string) { /* ... */ }
}
// Stage 3 returns a replacement — no descriptor mutation, no flags:
class ApiModern {
@logged // TS 5.0 default
fetch(id: string) { /* ... */ }
}// Class decorator returning a subclass (Stage 3) — the "replace the declaration" power
function withId<T extends new (...args: any[]) => object>(Base: T, _c: ClassDecoratorContext) {
return class extends Base {
id = crypto.randomUUID();
};
}
@withId class Widget {}
// new Widget().id is present at runtime, but note: the added field
// is NOT visible on the static type unless you also declare it.Stage 3 class decorator может вернуть subclass с новым полем — но static type не узнает о id, пока вы явно не объявите его в типе.
Legacy = mutation descriptor + metadata; Stage 3 = replacement + context. Runtime-поле ≠ автоматический static type.
