Декоратор класса машинописного текста: свойства ввода, определенные в функции декоратора

bar — это простой декоратор класса, добавляющий свойство к классу Foo.

function bar(target) {
    target.inDecorator = 'in decorator';
}

@bar
class Foo {
    inClass:string;
    inDecorator:string;
    constructor() {
        this.inClass = 'a string';
    }

    getInClass() {
        return this.inClass;
    }
}

console.log(Foo.inDecorator);
console.log(Foo.prototype.inDecorator);
const foo = new Foo();
console.log(foo.getInClass());
console.log(foo.inDecorator);

Единственный консольный лог, вызывающий ошибку, это первый, Foo.inDecorator, включение которого в ts 1.5.3 дает

Property 'inDecorator' does not exist on type 'typeof Foo'.

Насколько я могу судить, inDecorator должен быть определен в прототипе класса Foo и должен быть доступен в Foo, как если бы это была статическая опора. Запуск полученного файла js показывает undefined для доступа к прототипу, а также для нового объекта foo, однако Foo.inDecorator печатает правильно, даже если он является источником ошибки. Для большей ясности получаем

in decorator
undefined
a string
undefined

Любые идеи о том, как правильно ввести/добавить статическую опору или метод?

Спасибо!

Отредактировал это, так как изначально упустил из виду тот факт, что доступ к прототипу Foo.prototype.inDecorator не работал.


person low_ghost    schedule 01.08.2015    source источник


Ответы (1)


В декораторе target относится к функции — Foo — а не к прототипу — Foo.prototype.

Таким образом, в декораторе выполнение target.inDecorator = ... аналогично Foo.inDecorator = ..., а не Foo.prototype.inDecorator = ....

Вот один из способов сделать это:

interface BarStatic {
    new(): BarInstance;
    inDecorator: string;
}

interface BarInstance {
    inDecorator: string;
}

function bar(target: BarStatic) {
    target.inDecorator = 'static';
    // note that prototype will be `any` here though
    target.prototype.inDecorator = 'instance';
}

@bar
class Foo {
    static inDecorator: string; // required
    inDecorator: string;        // required
    inClass: string;

    constructor() {
        this.inClass = 'a string';
    }

    getInClass() {
        return this.inClass;
    }
}

console.log(Foo.inDecorator);           // static
console.log(Foo.prototype.inDecorator); // instance
const foo = new Foo();
console.log(foo.getInClass());          // a string
console.log(foo.inDecorator);           // instance
person David Sherret    schedule 01.08.2015
comment
это определенно работает, но кажется, что много лишнего кода и, конечно, не интуитивно понятно. почему inDecorator должен быть в базовом классе, если он такой же, как Foo.inDecorator? Если бы кто-то добавил статическую опору непосредственно в Foo с помощью static newProp = new string, пришлось бы ее также набирать таким странным образом? Нет способа реализовать интерфейс вместо расширения класса? Или используя статический inDecorator: string; вместо этого в классе Foo? Мои собственные эксперименты показывают, что нет. Но спасибо за рабочее решение! Я просто надеюсь, что машинописный текст имеет более лаконичный метод - person low_ghost; 01.08.2015
comment
Потрясающий! спасибо за это! в случае простого добавления реквизита из декоратора, я думаю, все сводится к static inDecorator: string; прямо в Foo, если вы не печатаете в интерфейсах и не добавляете в прототип. Клянусь, я пробовал это. :) Классическое наследование здесь намного чище, но я пытаюсь написать угловой 1.x, который выглядит и ощущается как 2.0, используя декораторы компонентов и представлений, чтобы выполнить большую часть директивной логики. Возможно, немного глупо. Эти функции также выполняют много другой работы, более специфичной для декоратора, но, похоже, не могли набрать реквизит в ts. Спасибо! - person low_ghost; 02.08.2015