Skip to content

Commit 9f8d5fd

Browse files
tkirda-bisonclaude
andcommitted
fix(types): widen TransformResult response parameter
`$.ajax` resolves with a payload whose shape is defined by the consumer's service, but `TransformResult` typed it `string | AutocompleteResponse`. That rejected the README's own non-standard-response example (TS2339) and also rejected a consumer-annotated `(response: MyResponse) => ...` callback (TS2322, parameter contravariance). `unknown` fixes neither, so the parameter is now `any` — the same type jQuery gives it. Fixes #891 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X29RAqzWDUD7UptThtJZGv
1 parent 6599b00 commit 9f8d5fd

3 files changed

Lines changed: 25 additions & 5 deletions

File tree

‎CLAUDE.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ The minified UMD is ~13 KB; the unminified is ~26 KB.
7272

7373
## Conventions
7474

75-
- TypeScript strict mode is on. Don't introduce `any` in public types. Internal `as unknown as X` casts are OK at jQuery boundaries where typings are imprecise.
75+
- TypeScript strict mode is on. Don't introduce `any` in public types. Internal `as unknown as X` casts are OK at jQuery boundaries where typings are imprecise. The one deliberate exception is `TransformResult`'s `response: any` (#891) — it's the raw server payload, jQuery types it `any`, and `unknown` breaks both the README example and consumer-annotated callbacks. Don't "tighten" it back.
7676
- The `Autocomplete` class explicitly marks every member `private` unless it's part of the documented public API in `readme.md` (`setOptions`, `clear`, `clearCache`, `disable`, `enable`, `hide`, `select`, `dispose`, plus the `options` field and the static `defaults`/`utils`). When adding a new member, default to `private`; only drop the keyword when you also add a row to the README's instance-method table. JS callers can still reach private members at runtime — they're a TypeScript-surface contract, not a runtime fence — but the contract is what consumers will rely on.
7777
- Methods use `this` directly. The one exception is `initialize()`, which aliases `const self = this` for the jQuery delegation handlers (`function (this: HTMLElement)`) that need both `$(this)` for the matched element AND access to the Autocomplete instance. Don't add new `that = this` aliases elsewhere — use arrow functions for callbacks instead.
7878
- Prefer native array methods (`.map`, `.filter`, `.find`, `.some`, `.indexOf`) over jQuery's `$.each` / `$.grep` / `$.map` / `$.inArray` in new code; the JS-source equivalents have already been swapped where semantics match.

‎readme.md‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,25 @@ $('#autocomplete').autocomplete({
256256
});
257257
```
258258

259+
`transformResult` receives the raw payload `$.ajax` resolved with, so its
260+
type is up to your service. In TypeScript you can annotate the parameter
261+
with your own response shape:
262+
263+
```ts
264+
interface MyResponse {
265+
myData: { valueField: string; dataField: number }[];
266+
}
267+
268+
$('#autocomplete').autocomplete({
269+
transformResult: (response: MyResponse) => ({
270+
suggestions: response.myData.map((item) => ({
271+
value: item.valueField,
272+
data: item.dataField,
273+
})),
274+
}),
275+
});
276+
```
277+
259278
## Grouping results
260279

261280
Set `groupBy` to a property name on `suggestion.data` to render group

‎src/types.ts‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ export type LookupFilter = (
2121
queryLowerCase: string
2222
) => boolean;
2323

24-
export type TransformResult = (
25-
response: string | AutocompleteResponse,
26-
originalQuery: string
27-
) => AutocompleteResponse;
24+
// `response` is whatever `$.ajax` resolved with — its shape is defined by the
25+
// consumer's server, not by us, and jQuery itself types it as `any`. `unknown`
26+
// won't do: it rejects both `response.myData` on an unannotated parameter and a
27+
// consumer-annotated `(response: MyResponse) => ...` (parameter contravariance).
28+
export type TransformResult = (response: any, originalQuery: string) => AutocompleteResponse;
2829

2930
export type FormatResult = (suggestion: Suggestion, currentValue: string, index?: number) => string;
3031

0 commit comments

Comments
 (0)