[Typescript] decorator example

Language/Typescript 2017.12.28 20:36


Working environment:
OS: Linux 4.4.0-104-generic #127-Ubuntu SMP Mon Dec 11 12:16:42 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
nodejs: 8.9.1
typescript: 2.6.2




<< class decorator >>


(() => {
///////////////////////////////////////////////////////////////////////////////
//
// Class decorator
//
///////////////////////////////////////////////////////////////////////////////
/**
 * See ClassDecorator type at lib.es5.d.ts
 * @param ctor constructor function. Prototype of constructor function
 *               is object for class-definition.
 */
function log<T extends Function>(ctor: T): T | void {
    // decorator is called with 'this' bound to global-object,
    console.assert(undefined !== this.console);
    console.assert(console === this.console);
    console.assert('function' === typeof(ctor));
    console.log('%o', ctor);
    let newConstructor: any = function (...args: Array<any>) {
        console.log('New: ' + ctor.name);
        let o: any = new (<any>ctor)(...args);
        // this is new constructor. So, '_test' is shown at console.log(<instance>)
        o._test = 'mytest';
        return o;
    };
    return newConstructor;
}

@log
class Person {
    constructor(
        public name: string,
        public surname: string
    ) { }

    get myname() {
        return this.name;
    }

    fullname(nick: string) {
        return `${this.name} ${this.surname} : ${nick}`;
    }
}

let p = new Person('name', 'surname');
// console.log('%o, %O', p, p);
console.assert(p.name === 'name');
console.assert(p.myname === 'name');
console.assert(p.fullname('N') === 'name surname : N');
console.assert((<any>p)._test === 'mytest');


///////////////////////////////////////////////////////////////////////////////
//
// Class decorator with argument.
//
///////////////////////////////////////////////////////////////////////////////
function logArg(nick: string) {
    return function<T extends Function>(ctor: T): T | void {
        let newCtor: any = function (...args: Array<any>) {
            // console.log('New: ' + fconstructor.name);
            let o: any = new (<any>ctor)(...args);
            o.nick = nick;
            return o;
        };
        return newCtor;
    };
}

@logArg('nick')
class Person2 {
    constructor(
        public name: string
    ) { }

    fullname(age: number) {
        return `${this.name} ${(<any>this).nick} : ${age}`;
    }
}

let p2 = new Person2('name');
// console.log(p);
console.assert(p2.name === 'name');
console.assert(p2.fullname(18) === 'name nick : 18');
console.assert((<any>p2).nick === 'nick');


///////////////////////////////////////////////////////////////////////////////
})();









<< method decorator >>

(() => {
///////////////////////////////////////////////////////////////////////////////
//
// Member decorator
//
///////////////////////////////////////////////////////////////////////////////

/**
 * See MethodDecorator at lib.es5.d.ts for detail types.
 * @param target class(prototype of class-constructor) where this method belongs to
 * @param key name of method
 * @param descriptor method(function)-property descriptor
 */
function log(
    target: any, key: string | symbol, descriptor: TypedPropertyDescriptor<any>
): TypedPropertyDescriptor<any> | void {
    // decorator is called with 'this' bound to global-object,
    console.assert(undefined !== this.console);
    console.assert(console === this.console);

    console.assert('fullname' === key);

    // This is ONLY FOR DEMO and EXAMPLE! - NOT RECOMMENDED!
    // Add new property to prototype of class-constructor.
    // (applied to all class instance!)
    target['newattr'] = 'hello';

    // save a reference to the original method this way we keep the values currently in the
    // descriptor and don't overwrite what another decorator might have done to the descriptor.
    if (descriptor === undefined) {
        descriptor = Object.getOwnPropertyDescriptor(target, key)!;
    }

    //editing the descriptor/value parameter
    let orig = descriptor.value;
    descriptor.value = function () {
        console.log(`Called: ${key}`);
        return orig!.apply(this, arguments);
    };

    return descriptor;
}


class Person {
    constructor(
        public name: string,
    ) { }

    get myname() {
        return this.name;
    }

    @log
    fullname(newname: string, nick: string) {
        this.name = newname;
        return `${this.name}:${nick}`;
    }
}

let p = new Person('name');
let p2 = new Person('name2');
// console.log(p.fullname('newname', 'nick'));
console.assert('name' === p.myname);
console.assert('name2' === p2.myname);
console.assert('hello' === (<any>p).newattr);
console.assert('hello' === (<any>p2).newattr);
console.assert('newname:nick' === p.fullname('newname', 'nick'));
console.assert('newname' === p.myname);
console.assert(`hello` === (<any>p).newattr);

console.log(p);

///////////////////////////////////////////////////////////////////////////////
//
// Member decorator with argument
//
///////////////////////////////////////////////////////////////////////////////

// Same way with class decorator.

///////////////////////////////////////////////////////////////////////////////
})();





<< parameter decorator >>

(() => {
///////////////////////////////////////////////////////////////////////////////
//
// Parameter decorator
//
///////////////////////////////////////////////////////////////////////////////

/**
 *
 * @param target class(prototype of class-constructor) where this method belongs in
 * @param key name of method where this parameter belongs to
 * @param index parameter position in function - stars at 0(the first parameter).
 */
function log(target: any, key: string | symbol, index: number): void {
    // decorator is called with 'this' bound to global-object,
    console.assert(undefined !== this.console);
    console.assert(console === this.console);

    console.assert('fullname' === key);
    console.assert(1 === index);
}


class Person {
    constructor(
        public name: string,
    ) { }

    get myname() {
        return this.name;
    }

    fullname(newname: string, @log nick: string) {
        this.name = newname;
        return `${this.name}:${nick}`;
    }
}

let p = new Person('name');
// console.log(p.fullname('newname', 'nick'));
console.assert('newname:nick' === p.fullname('newname', 'nick'));
console.assert('newname' === p.myname);

///////////////////////////////////////////////////////////////////////////////
})();






<< property decorator >>

(() => {
///////////////////////////////////////////////////////////////////////////////
//
// Property decorator
//
///////////////////////////////////////////////////////////////////////////////

/**
 *
 * @param target class(prototype of class-constructor) where this method belongs in
 * @param key name of method where this parameter belongs to
 */
function log(target: any, key: string | symbol): void {
    // decorator is called with 'this' bound to global-object,
    console.assert(undefined !== this.console);
    console.assert(console === this.console);
    console.assert('name' === key || 'obj' === key);

    let internalKey = `$${key}`;
    // property getter
    let getter = function () {
        console.log(`Get: ${key} => ${this[internalKey]}`);
        return this[internalKey];
    };

    // property setter
    let setter = function (newVal: any) {
        console.log(`Set: ${key} => ${newVal}`);
        this[internalKey] = newVal;
    };

    // Delete property.
    if (delete target[key]) {
        console.assert(undefined === target[`$${key}`]);
        // Create new property with getter and setter
        Object.defineProperty(target, key, {
            get: getter,
            set: setter,
            enumerable: true,
            configurable: true
        });
    }
}

class Person {
    @log
    public name = 'init';
    @log
    public obj = {};

    constructor(name: string) {
        this.name = name;
    }

    get myname() {
        return this.name;
    }

    fullname(newname: string, nick: string) {
        this.name = newname;
        return `${this.name}:${nick}`;
    }
}

let p = new Person('name');
p.name = 'hello';
p.obj = {a: 1};

console.assert((<any>p)['$name'] === p.name);
console.assert((<any>p)['$obj'] === p.obj);
console.assert('newname:nick' === p.fullname('newname', 'nick'));
console.assert('newname' === p.myname);

// console.log('%o', p);

///////////////////////////////////////////////////////////////////////////////
})();


Trackback 0 : Comment 0

[Bash] 'set -e' inheritance...???

Language/Bash 2017.05.19 20:33



======================================================

       −e    When this option is on, when any command fails (for any of the reasons listed in Section 2.8.1, Consequences of Shell Errors or by  return‐
             ing an exit status greater than zero), the shell immediately shall exit with the following exceptions:

              1. The  failure  of any individual command in a multi-command pipeline shall not cause the shell to exit. Only the failure of the pipeline
                 itself shall be considered.

              2. The −e setting shall be ignored when executing the compound list following the while, until, if, or  elif  reserved  word,  a  pipeline
                 beginning with the !  reserved word, or any command of an AND-OR list other than the last.

              3. If  the exit status of a compound command other than a subshell command was the result of a failure while −e was being ignored, then −e
                 shall not apply to this command.

             This requirement applies to the shell environment and each subshell environment separately. For example, in:

                 set -e; (false; echo one) | cat; echo two

             the false command causes the subshell to exit without executing echo one; however, echo two is executed because  the  exit  status  of  the
             pipeline (false; echo one) | cat is zero.

==========================


#!/bin/bash

set -e

function myf {
    echo "Enter myf"
    false
    echo "Exit myf"
}

echo "Start"
myf
echo "End"



$ ./x.sh
Start
Enter myf


=======================

#!/bin/bash

set -e

function myf {
    echo "Enter myf"
    false
    echo "Exit myf"
}

echo "Start"
myf || true
echo "End"


$ ./x.sh
Start
Enter myf
Exit myf
End


========================

#!/bin/bash

set -e

function myf {
    echo 'myf' >&2
    exit 2
}

function test {
    a=$(myf)
    echo "TEST DONE"
}

a=$(test)
echo "DONE"

$ ./x.sh
myf
DONE


===========================

#!/bin/bash

set -e

function myf {
    echo 'myf' >&2
    exit 2
}

a=$(myf)
echo "TEST DONE"



$ ./x.sh
myf


====================

#!/bin/bash

set -e

function myf {
    echo 'myf' >&2
    false
    echo "myf DONE"
}

a=$(myf)
echo "DONE"



$ ./x.sh
myf
DONE


=======================

#!/bin/bash

set -e

function myf {
    echo 'myf' >&2
    false
    echo "myf DONE"
}

function test {
    a=$(myf)
    echo 'test DONE'
}

a=$(test)
echo "DONE"


$ ./x.sh
myf
DONE


'Language > Bash' 카테고리의 다른 글

[Bash] 'set -e' inheritance...???  (0) 2017.05.19
Bash print call stack at ERR(trap)  (0) 2017.03.08
Trackback 0 : Comment 0

[Python] __iter__ method of class at add operator with list...

Language/Python 2017.05.19 20:32


class L(object):
    def __init__(self, lst):
        self.l = lst

    def __iter__(self):
        print('iter..')
        for l in self.l:
            yield l

    def __str__(self):
        return ' '.join(self.l)


l1 = L(['1', '2', '3'])
l2 = []
ll2+= l1
print(' '.join(l2))


$ ./a.py
iter..
1 2 3



Trackback 0 : Comment 0