From c091134cfa2f55ab64bfcf481e9ded1c96c32781 Mon Sep 17 00:00:00 2001 From: gwansikk Date: Tue, 14 Apr 2026 13:53:07 +0900 Subject: [PATCH 1/4] fix(types): lastResult should reflect resolved value --- packages/pacer/src/async-debouncer.ts | 2 +- packages/pacer/src/async-rate-limiter.ts | 2 +- packages/pacer/src/async-throttler.ts | 2 +- packages/pacer/tests/async-debouncer.test.ts | 21 +++++++++++++++- .../pacer/tests/async-rate-limiter.test.ts | 24 ++++++++++++++++++- packages/pacer/tests/async-throttler.test.ts | 21 +++++++++++++++- 6 files changed, 66 insertions(+), 6 deletions(-) diff --git a/packages/pacer/src/async-debouncer.ts b/packages/pacer/src/async-debouncer.ts index d24d721a7..c95bf5ecf 100644 --- a/packages/pacer/src/async-debouncer.ts +++ b/packages/pacer/src/async-debouncer.ts @@ -29,7 +29,7 @@ export interface AsyncDebouncerState { /** * The result from the most recent successful function execution */ - lastResult: ReturnType | undefined + lastResult: Awaited> | undefined /** * Number of times maybeExecute has been called (for reduction calculations) */ diff --git a/packages/pacer/src/async-rate-limiter.ts b/packages/pacer/src/async-rate-limiter.ts index 5ac9be42d..0eb0cff63 100644 --- a/packages/pacer/src/async-rate-limiter.ts +++ b/packages/pacer/src/async-rate-limiter.ts @@ -25,7 +25,7 @@ export interface AsyncRateLimiterState { /** * The result from the most recent successful function execution */ - lastResult: ReturnType | undefined + lastResult: Awaited> | undefined /** * Number of function executions that have been rejected due to rate limiting */ diff --git a/packages/pacer/src/async-throttler.ts b/packages/pacer/src/async-throttler.ts index b6bc30b3a..0fa575354 100644 --- a/packages/pacer/src/async-throttler.ts +++ b/packages/pacer/src/async-throttler.ts @@ -29,7 +29,7 @@ export interface AsyncThrottlerState { /** * The result from the most recent successful function execution */ - lastResult: ReturnType | undefined + lastResult: Awaited> | undefined /** * Number of times maybeExecute has been called (for reduction calculations) */ diff --git a/packages/pacer/tests/async-debouncer.test.ts b/packages/pacer/tests/async-debouncer.test.ts index 66ac0ca99..7897921fc 100644 --- a/packages/pacer/tests/async-debouncer.test.ts +++ b/packages/pacer/tests/async-debouncer.test.ts @@ -1,4 +1,4 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { afterEach, beforeEach, describe, expect, expectTypeOf, it, vi } from 'vitest' import { AsyncDebouncer, asyncDebounce } from '../src/async-debouncer' describe('AsyncDebouncer', () => { @@ -1359,4 +1359,23 @@ describe('asyncDebounce helper function', () => { expect(debouncer.getAbortSignal()).toBeNull() }) }) + + describe('Type Safety', () => { + it('should type lastResult as the awaited return type, not a Promise', () => { + const debouncer = new AsyncDebouncer(async () => 'hello', { wait: 100 }) + expectTypeOf(debouncer.store.state.lastResult).toEqualTypeOf< + string | undefined + >() + }) + + it('should type lastResult correctly for non-primitive return types', () => { + const debouncer = new AsyncDebouncer( + async () => ({ id: 1, name: 'test' }), + { wait: 100 }, + ) + expectTypeOf(debouncer.store.state.lastResult).toEqualTypeOf< + { id: number; name: string } | undefined + >() + }) + }) }) diff --git a/packages/pacer/tests/async-rate-limiter.test.ts b/packages/pacer/tests/async-rate-limiter.test.ts index 22bcae3c8..0399fd2a4 100644 --- a/packages/pacer/tests/async-rate-limiter.test.ts +++ b/packages/pacer/tests/async-rate-limiter.test.ts @@ -1,4 +1,4 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { afterEach, beforeEach, describe, expect, expectTypeOf, it, vi } from 'vitest' import { AsyncRateLimiter, asyncRateLimit } from '../src/async-rate-limiter' describe('AsyncRateLimiter', () => { @@ -775,4 +775,26 @@ describe('asyncRateLimit', () => { expect(rateLimiter.getAbortSignal()).toBeNull() }) }) + + describe('Type Safety', () => { + it('should type lastResult as the awaited return type, not a Promise', () => { + const rateLimiter = new AsyncRateLimiter(async () => 'hello', { + limit: 5, + window: 1000, + }) + expectTypeOf(rateLimiter.store.state.lastResult).toEqualTypeOf< + string | undefined + >() + }) + + it('should type lastResult correctly for non-primitive return types', () => { + const rateLimiter = new AsyncRateLimiter( + async () => ({ id: 1, name: 'test' }), + { limit: 5, window: 1000 }, + ) + expectTypeOf(rateLimiter.store.state.lastResult).toEqualTypeOf< + { id: number; name: string } | undefined + >() + }) + }) }) diff --git a/packages/pacer/tests/async-throttler.test.ts b/packages/pacer/tests/async-throttler.test.ts index 2cb1072ef..c5fd65676 100644 --- a/packages/pacer/tests/async-throttler.test.ts +++ b/packages/pacer/tests/async-throttler.test.ts @@ -1,4 +1,4 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest' +import { beforeEach, describe, expect, expectTypeOf, it, vi } from 'vitest' import { AsyncThrottler } from '../src/async-throttler' describe('AsyncThrottler', () => { @@ -998,4 +998,23 @@ describe('AsyncThrottler', () => { expect(throttler.getAbortSignal()).toBeNull() }) }) + + describe('Type Safety', () => { + it('should type lastResult as the awaited return type, not a Promise', () => { + const throttler = new AsyncThrottler(async () => 'hello', { wait: 100 }) + expectTypeOf(throttler.store.state.lastResult).toEqualTypeOf< + string | undefined + >() + }) + + it('should type lastResult correctly for non-primitive return types', () => { + const throttler = new AsyncThrottler( + async () => ({ id: 1, name: 'test' }), + { wait: 100 }, + ) + expectTypeOf(throttler.store.state.lastResult).toEqualTypeOf< + { id: number; name: string } | undefined + >() + }) + }) }) From 04e5d34c0ef2dd16361d8ddaeee9b2c28f964360 Mon Sep 17 00:00:00 2001 From: gwansikk Date: Sat, 18 Apr 2026 15:37:13 +0900 Subject: [PATCH 2/4] chore: remove type test --- packages/pacer/tests/async-debouncer.test.ts | 29 ++++++----------- .../pacer/tests/async-rate-limiter.test.ts | 32 ++++++------------- packages/pacer/tests/async-throttler.test.ts | 19 ----------- 3 files changed, 18 insertions(+), 62 deletions(-) diff --git a/packages/pacer/tests/async-debouncer.test.ts b/packages/pacer/tests/async-debouncer.test.ts index 7897921fc..40b71f748 100644 --- a/packages/pacer/tests/async-debouncer.test.ts +++ b/packages/pacer/tests/async-debouncer.test.ts @@ -1,4 +1,12 @@ -import { afterEach, beforeEach, describe, expect, expectTypeOf, it, vi } from 'vitest' +import { + afterEach, + beforeEach, + describe, + expect, + expectTypeOf, + it, + vi, +} from 'vitest' import { AsyncDebouncer, asyncDebounce } from '../src/async-debouncer' describe('AsyncDebouncer', () => { @@ -1359,23 +1367,4 @@ describe('asyncDebounce helper function', () => { expect(debouncer.getAbortSignal()).toBeNull() }) }) - - describe('Type Safety', () => { - it('should type lastResult as the awaited return type, not a Promise', () => { - const debouncer = new AsyncDebouncer(async () => 'hello', { wait: 100 }) - expectTypeOf(debouncer.store.state.lastResult).toEqualTypeOf< - string | undefined - >() - }) - - it('should type lastResult correctly for non-primitive return types', () => { - const debouncer = new AsyncDebouncer( - async () => ({ id: 1, name: 'test' }), - { wait: 100 }, - ) - expectTypeOf(debouncer.store.state.lastResult).toEqualTypeOf< - { id: number; name: string } | undefined - >() - }) - }) }) diff --git a/packages/pacer/tests/async-rate-limiter.test.ts b/packages/pacer/tests/async-rate-limiter.test.ts index 0399fd2a4..f3ef4a9f4 100644 --- a/packages/pacer/tests/async-rate-limiter.test.ts +++ b/packages/pacer/tests/async-rate-limiter.test.ts @@ -1,4 +1,12 @@ -import { afterEach, beforeEach, describe, expect, expectTypeOf, it, vi } from 'vitest' +import { + afterEach, + beforeEach, + describe, + expect, + expectTypeOf, + it, + vi, +} from 'vitest' import { AsyncRateLimiter, asyncRateLimit } from '../src/async-rate-limiter' describe('AsyncRateLimiter', () => { @@ -775,26 +783,4 @@ describe('asyncRateLimit', () => { expect(rateLimiter.getAbortSignal()).toBeNull() }) }) - - describe('Type Safety', () => { - it('should type lastResult as the awaited return type, not a Promise', () => { - const rateLimiter = new AsyncRateLimiter(async () => 'hello', { - limit: 5, - window: 1000, - }) - expectTypeOf(rateLimiter.store.state.lastResult).toEqualTypeOf< - string | undefined - >() - }) - - it('should type lastResult correctly for non-primitive return types', () => { - const rateLimiter = new AsyncRateLimiter( - async () => ({ id: 1, name: 'test' }), - { limit: 5, window: 1000 }, - ) - expectTypeOf(rateLimiter.store.state.lastResult).toEqualTypeOf< - { id: number; name: string } | undefined - >() - }) - }) }) diff --git a/packages/pacer/tests/async-throttler.test.ts b/packages/pacer/tests/async-throttler.test.ts index c5fd65676..97f3dfa7e 100644 --- a/packages/pacer/tests/async-throttler.test.ts +++ b/packages/pacer/tests/async-throttler.test.ts @@ -998,23 +998,4 @@ describe('AsyncThrottler', () => { expect(throttler.getAbortSignal()).toBeNull() }) }) - - describe('Type Safety', () => { - it('should type lastResult as the awaited return type, not a Promise', () => { - const throttler = new AsyncThrottler(async () => 'hello', { wait: 100 }) - expectTypeOf(throttler.store.state.lastResult).toEqualTypeOf< - string | undefined - >() - }) - - it('should type lastResult correctly for non-primitive return types', () => { - const throttler = new AsyncThrottler( - async () => ({ id: 1, name: 'test' }), - { wait: 100 }, - ) - expectTypeOf(throttler.store.state.lastResult).toEqualTypeOf< - { id: number; name: string } | undefined - >() - }) - }) }) From cd23d53d55ea60a386529c4953585f10969d3ab5 Mon Sep 17 00:00:00 2001 From: gwansikk Date: Sat, 18 Apr 2026 15:38:14 +0900 Subject: [PATCH 3/4] chore: remove unused import --- packages/pacer/tests/async-debouncer.test.ts | 10 +--------- packages/pacer/tests/async-rate-limiter.test.ts | 10 +--------- packages/pacer/tests/async-throttler.test.ts | 2 +- 3 files changed, 3 insertions(+), 19 deletions(-) diff --git a/packages/pacer/tests/async-debouncer.test.ts b/packages/pacer/tests/async-debouncer.test.ts index 40b71f748..66ac0ca99 100644 --- a/packages/pacer/tests/async-debouncer.test.ts +++ b/packages/pacer/tests/async-debouncer.test.ts @@ -1,12 +1,4 @@ -import { - afterEach, - beforeEach, - describe, - expect, - expectTypeOf, - it, - vi, -} from 'vitest' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { AsyncDebouncer, asyncDebounce } from '../src/async-debouncer' describe('AsyncDebouncer', () => { diff --git a/packages/pacer/tests/async-rate-limiter.test.ts b/packages/pacer/tests/async-rate-limiter.test.ts index f3ef4a9f4..22bcae3c8 100644 --- a/packages/pacer/tests/async-rate-limiter.test.ts +++ b/packages/pacer/tests/async-rate-limiter.test.ts @@ -1,12 +1,4 @@ -import { - afterEach, - beforeEach, - describe, - expect, - expectTypeOf, - it, - vi, -} from 'vitest' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { AsyncRateLimiter, asyncRateLimit } from '../src/async-rate-limiter' describe('AsyncRateLimiter', () => { diff --git a/packages/pacer/tests/async-throttler.test.ts b/packages/pacer/tests/async-throttler.test.ts index 97f3dfa7e..2cb1072ef 100644 --- a/packages/pacer/tests/async-throttler.test.ts +++ b/packages/pacer/tests/async-throttler.test.ts @@ -1,4 +1,4 @@ -import { beforeEach, describe, expect, expectTypeOf, it, vi } from 'vitest' +import { beforeEach, describe, expect, it, vi } from 'vitest' import { AsyncThrottler } from '../src/async-throttler' describe('AsyncThrottler', () => { From e8d0bcd4b4cf1dda8c647ddead62a27e318a4e7b Mon Sep 17 00:00:00 2001 From: gwansikk Date: Sat, 18 Apr 2026 15:48:50 +0900 Subject: [PATCH 4/4] chore: add changeset --- .changeset/pretty-llamas-happen.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/pretty-llamas-happen.md diff --git a/.changeset/pretty-llamas-happen.md b/.changeset/pretty-llamas-happen.md new file mode 100644 index 000000000..0476df312 --- /dev/null +++ b/.changeset/pretty-llamas-happen.md @@ -0,0 +1,5 @@ +--- +'@tanstack/pacer': patch +--- + +lastResult should reflect resolved value