Skip to content

Commit 57d380f

Browse files
authored
Merge pull request #8 from github/feat-add-support-for-typescript-decorators
Add support for typescript decorators
2 parents d0f03c7 + 6dbc6b8 commit 57d380f

File tree

10 files changed

+1436
-4886
lines changed

10 files changed

+1436
-4886
lines changed

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,21 @@ await delay(100)
5353
| throttle(fn, 100, {once: true, start: false})| 2 |
5454
| debounce(fn, 100) | 10 |
5555
```
56+
57+
### TypeScript Decorators Support!
58+
59+
This package also includes a decorator module which can be used to provide [TypeScript Decorator](https://www.typescriptlang.org/docs/handbook/decorators.html#decorators) annotations to functions.
60+
61+
Here's an example, showing what you need to do:
62+
63+
```typescript
64+
import {throttle} from '@github/mini-throttle/decorators'
65+
// ^ note: add `/decorators` to the import to get decorators
66+
67+
class MyClass {
68+
@throttle(100, { start: false }) // <- Just like normal throttle, but you omit the callback argument
69+
doThings() {
70+
// `MyClass.prototype.doThings` will be throttled!
71+
}
72+
}
73+
```

decorators.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import {debounce as db, throttle as th, ThrottleOptions} from './index'
2+
3+
export function throttle(wait = 0, opts: ThrottleOptions = {}) {
4+
return (proto: unknown, name: string, descriptor: PropertyDescriptor) => {
5+
if (!descriptor || typeof descriptor.value !== 'function') {
6+
throw new Error('debounce can only decorate functions')
7+
}
8+
const fn = descriptor.value
9+
descriptor.value = th(fn, wait, opts)
10+
Object.defineProperty(proto, name, descriptor)
11+
}
12+
}
13+
14+
export function debounce(wait = 0, opts: ThrottleOptions = {}) {
15+
return (proto: unknown, name: string, descriptor: PropertyDescriptor) => {
16+
if (!descriptor || typeof descriptor.value !== 'function') {
17+
throw new Error('debounce can only decorate functions')
18+
}
19+
const fn = descriptor.value
20+
descriptor.value = db(fn, wait, opts)
21+
Object.defineProperty(proto, name, descriptor)
22+
}
23+
}

decorators/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"main": "../dist/umd/decorators.js",
3+
"module": "../dist/decorators.js"
4+
}

index.d.ts

Lines changed: 0 additions & 26 deletions
This file was deleted.
Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,45 @@
1-
/* @flow strict */
2-
3-
type ThrottleOptions = {|
4-
start?: boolean,
5-
middle?: boolean,
1+
export interface ThrottleOptions {
2+
/**
3+
* Fire immediately on the first call.
4+
*/
5+
start?: boolean
6+
/**
7+
* Fire as soon as `wait` has passed.
8+
*/
9+
middle?: boolean
10+
/**
11+
* Cancel after the first successful call.
12+
*/
613
once?: boolean
7-
|}
8-
export function throttle<T: $ReadOnlyArray<mixed>>(
9-
callback: (...T) => mixed,
10-
wait: number = 0,
14+
}
15+
16+
interface Throttler<T extends unknown[]> {
17+
(...args: T): void
18+
cancel(): void
19+
}
20+
21+
export function throttle<T extends unknown[]>(
22+
callback: (...args: T) => unknown,
23+
wait = 0,
1124
{start = true, middle = true, once = false}: ThrottleOptions = {}
12-
): (...T) => void {
25+
): Throttler<T> {
1326
let last = 0
14-
let timer
27+
let timer: number | undefined
1528
let cancelled = false
16-
const fn = (...args) => {
29+
function fn(this: unknown, ...args: T) {
1730
if (cancelled) return
1831
const delta = Date.now() - last
1932
last = Date.now()
2033
if (start) {
21-
//eslint-disable-next-line flowtype/no-flow-fix-me-comments
22-
// $FlowFixMe this isn't a const
2334
start = false
24-
callback(...args)
35+
callback.apply(this, args)
2536
if (once) fn.cancel()
2637
} else if ((middle && delta < wait) || !middle) {
2738
clearTimeout(timer)
2839
timer = setTimeout(
2940
() => {
3041
last = Date.now()
31-
callback(...args)
42+
callback.apply(this, args)
3243
if (once) fn.cancel()
3344
},
3445
!middle ? wait : wait - delta
@@ -42,10 +53,10 @@ export function throttle<T: $ReadOnlyArray<mixed>>(
4253
return fn
4354
}
4455

45-
export function debounce<T: $ReadOnlyArray<mixed>>(
46-
callback: (...T) => mixed,
47-
wait: number = 0,
56+
export function debounce<T extends unknown[]>(
57+
callback: (...args: T) => unknown,
58+
wait = 0,
4859
{start = false, middle = false, once = false}: ThrottleOptions = {}
49-
): (...T) => void {
60+
): Throttler<T> {
5061
return throttle(callback, wait, {start, middle, once})
5162
}

0 commit comments

Comments
 (0)