diff --git a/core-decorators/core-decorators-tests.ts b/core-decorators/core-decorators-tests.ts index e4a31432b..1731c4193 100644 --- a/core-decorators/core-decorators-tests.ts +++ b/core-decorators/core-decorators-tests.ts @@ -6,18 +6,25 @@ import { autobind } from 'core-decorators'; +@autobind class Person { @autobind getPerson() { return this; } + + getPersonAgain() { + return this; + } } let person = new Person(); -let getPerson = person.getPerson; +let { getPerson, getPersonAgain } = person; getPerson() === person; +getPersonAgain() === person; + // // @readonly // @@ -93,6 +100,7 @@ person2.facepalmHarder(); // @debounce // + import { debounce } from 'core-decorators'; class Editor { @@ -105,6 +113,22 @@ class Editor { } } +// +// @throttle +// + +import { throttle } from 'core-decorators'; + +class Editor2 { + + content = ''; + + @throttle(500, {leading: false}) + updateContent(content: string) { + this.content = content; + } +} + // // @suppressWarnings // @@ -166,4 +190,116 @@ Object.defineProperty(dinner3, 'entree', { }); // Cannot redefine property: entree +// +// @decorate +// + +declare function memoize(func: T): T; +import { decorate } from 'core-decorators'; + +var count = 0; + +class Task { + @decorate(memoize) + doSomethingExpensive(data: any) { + count++; + // something expensive; + return data; + } +} + +var task = new Task(); +var data = [1, 2, 3]; + +task.doSomethingExpensive(data); +task.doSomethingExpensive(data); + +count === 1; +// true + +// +// @lazyInitialize +// + +import { lazyInitialize } from 'core-decorators'; + +function createHugeBuffer() { + console.log('huge buffer created'); + return new Array(1000000); +} + +class Editor3 { + @lazyInitialize + hugeBuffer = createHugeBuffer(); +} + +var editor = new Editor3(); +// createHugeBuffer() has not been called yet + +editor.hugeBuffer; +// logs 'huge buffer created', now it has been called + +editor.hugeBuffer; +// already initialized and equals our buffer, so +// createHugeBuffer() is not called again + +//TODO: For @mixin, I don't know how we can make it work for TypeScript... +// +// @mixin (alias: @mixins) +// + +import { mixin } from 'core-decorators'; + +const SingerMixin = { + sing(sound: string) { + alert(sound); + } +}; + +const FlyMixin = { + // All types of property descriptors are supported + get speed(): number { return 42; }, + fly() {}, + land() {} +}; + +@mixin(SingerMixin, FlyMixin) +class Bird { + singMatingCall() { + //TODO: For @mixin, I don't know how we can make it work for TypeScript... + // this.sing('tweet tweet'); + } +} + +var bird = new Bird(); +bird.singMatingCall(); +// alerts "tweet tweet" + +// +// @time +// + +import { time } from 'core-decorators'; + +let myConsole = { + time: function(label: string) { /* custom time() method */ }, + timeEnd: function(label: string) { /* custom timeEnd method */ }, + log: function(str: any) { /* custom log method */ } +}; + +class Bird2 { + @time('sing') + sing() { + } + + @time('sing2', myConsole) + sing2() { + + } +} + +var bird2 = new Bird2(); +bird2.sing(); // console.time label will be 'sing-0' +bird2.sing(); // console.time label will be 'sing-1' + diff --git a/core-decorators/core-decorators.d.ts b/core-decorators/core-decorators.d.ts index 160802fc1..0d1bba186 100644 --- a/core-decorators/core-decorators.d.ts +++ b/core-decorators/core-decorators.d.ts @@ -1,4 +1,4 @@ -// Type definitions for core-decorators.js v0.1.5 +// Type definitions for core-decorators.js v0.10 // Project: https://github.com/jayphelps/core-decorators.js // Definitions by: Qubo // Definitions: https://github.com/borisyankov/DefinitelyTyped @@ -32,11 +32,24 @@ declare module "core-decorators" { url: string; } + export interface ThrottleOptions { + /** allows to trigger function on the leading. */ + leading?: boolean; + /** allows to trigger function on the trailing edge of the wait interval. */ + trailing?: boolean; + } + + export interface Console { + log(message?: any, ...optionalParams: any[]): void; + time(timerName?: string): void; + timeEnd(timerName?: string): void; + } + /** * Forces invocations of this function to always have this refer to the class instance, * even if the function is passed around or would otherwise lose its this context. e.g. var fn = context.method; */ - var autobind: MethodDecorator; + var autobind: Function; /** * Marks a property or method as not being writable. */ @@ -57,6 +70,10 @@ declare module "core-decorators" { * Creates a new debounced function which will be invoked after wait milliseconds since the time it was invoked. Default timeout is 300 ms. */ var debounce: (wait: number) => MethodDecorator; + /** + * Creates a new throttled function which will be invoked in every wait milliseconds. Default timeout is 300 ms. + */ + var throttle: (wait: number, options?: ThrottleOptions) => MethodDecorator; /** * Suppresses any JavaScript console.warn() call while the decorated function is called. (i.e. on the stack) */ @@ -73,6 +90,30 @@ declare module "core-decorators" { * Initial implementation included, likely slow. WIP. */ var memoize: MethodDecorator; + /** + * Immediately applies the provided function and arguments to the method, allowing you to wrap methods with arbitrary helpers like those provided by lodash. + * The first argument is the function to apply, all further arguments will be passed to that decorating function. + */ + var decorate: (func: Function, ...args: any[]) => MethodDecorator; + /** + * Prevents a property initializer from running until the decorated property is actually looked up. + * Useful to prevent excess allocations that might otherwise not be used, but be careful not to over-optimize things. + */ + var lazyInitialize: PropertyDecorator; + /** + * Mixes in all property descriptors from the provided Plain Old JavaScript Objects (aka POJOs) as arguments. + * Mixins are applied in the order they are passed, but do not override descriptors already on the class, including those inherited traditionally. + */ + var mixin: (...mixins: any[]) => ClassDecorator; + /** + * Mixes in all property descriptors from the provided Plain Old JavaScript Objects (aka POJOs) as arguments. + * Mixins are applied in the order they are passed, but do not override descriptors already on the class, including those inherited traditionally. + */ + var mixins: (...mixins: any[]) => ClassDecorator; + /** + * Uses console.time and console.timeEnd to provide function timings with a unique label whose default prefix is ClassName.method. Supply a first argument to override the prefix: + */ + var time: (label: string, console?: Console) => MethodDecorator; export { autobind, @@ -81,9 +122,15 @@ declare module "core-decorators" { deprecate, deprecated, debounce, + throttle, suppressWarnings, nonenumerable, nonconfigurable, - memoize // WIP + memoize, + decorate, + lazyInitialize, + mixin, + mixins, + time, }; }