[createInterfaceApi] typescript allows mutations to have array params (#36581)
components/ai_chat/resources/page/api/ai_chat_api.ts had trouble with typescript intellisense due to the process file mutation functions now having an array as their first param. Apparently due to contravariance checks
This commit is contained in:
@@ -476,6 +476,49 @@ describe('createInterfaceApi', () => {
|
||||
expect(mutationFn).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('accepts mutations defined via endpointsFor under strict function types', async () => {
|
||||
// Regression: previously, the `RawEndpoints` index signature used
|
||||
// `EndpointDef<any[], any>`, which made tuple-typed mutations like
|
||||
// `MutationEndpointDefinition<[Uint8Array, string], …>` fail assignability
|
||||
// under `strictFunctionTypes` because of contravariant `onMutate(variables: P)`
|
||||
// callbacks. The signature now uses `EndpointDef<any, any>` to side-step
|
||||
// that.
|
||||
type UploadedFile = { name: string }
|
||||
type MyInterface = {
|
||||
processImageFile: (
|
||||
fileData: number[],
|
||||
filename: string,
|
||||
) => Promise<{ processedFile: UploadedFile | null }>
|
||||
processPdfFile: (
|
||||
fileData: number[],
|
||||
filename: string,
|
||||
) => Promise<{ processedFile: UploadedFile | null }>
|
||||
}
|
||||
const impl: MyInterface = {
|
||||
processImageFile: (_d, n) =>
|
||||
Promise.resolve({ processedFile: { name: n } }),
|
||||
processPdfFile: (_d, n) =>
|
||||
Promise.resolve({ processedFile: { name: n } }),
|
||||
}
|
||||
|
||||
const api = createInterfaceApi({
|
||||
actions: {},
|
||||
endpoints: {
|
||||
...endpointsFor(impl, {
|
||||
processImageFile: {
|
||||
mutationResponse: (result) => result.processedFile,
|
||||
},
|
||||
processPdfFile: {
|
||||
mutationResponse: (result) => result.processedFile,
|
||||
},
|
||||
}),
|
||||
},
|
||||
})
|
||||
|
||||
const result = await api.processImageFile([[1, 2, 3], 'image.png'])
|
||||
expect(result).toEqual({ name: 'image.png' })
|
||||
})
|
||||
|
||||
it('can create void mutations that have a parameter', async () => {
|
||||
const mutationFn = jest.fn((hi: string) => {
|
||||
return Promise.resolve()
|
||||
|
||||
@@ -180,7 +180,14 @@ export function createInterfaceApi<
|
||||
string,
|
||||
Function | Record<string, Function>
|
||||
>,
|
||||
const RawEndpoints extends Record<string, EndpointDef<readonly any[], any>>,
|
||||
// Use `EndpointDef<any, any>` (not `any[]`) so that specific endpoint
|
||||
// definitions remain assignable under `strictFunctionTypes`. With `any[]`,
|
||||
// mutation callbacks like `onMutate: (variables: [a, b]) => …` fail
|
||||
// contravariance checks against `(variables: any[]) => …` because tuples
|
||||
// are narrower than `any[]`. Switching to `any` makes the parameter slot
|
||||
// bivariant and side-steps the variance issue without losing inference on
|
||||
// the concrete `RawEndpoints` type below.
|
||||
const RawEndpoints extends Record<string, EndpointDef<any, any>>,
|
||||
EventDefinitions extends Record<string, EventDef<any[], any>> = {},
|
||||
>(config: {
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user