diff --git a/types/react-instantsearch-core/index.d.ts b/types/react-instantsearch-core/index.d.ts index b38db4c718..68f977b538 100644 --- a/types/react-instantsearch-core/index.d.ts +++ b/types/react-instantsearch-core/index.d.ts @@ -116,6 +116,10 @@ export interface ConnectorDescription { cleanUp?(this: React.Component, props: TExposed, searchState: SearchState): SearchState; } +export type ConnectorProvided = TProvided & + { refine: (...args: any[]) => any, createURL: (...args: any[]) => string } & + { searchForItems: (...args: any[]) => any } + /** * Connectors are the HOC used to transform React components * into InstantSearch widgets. @@ -128,8 +132,12 @@ export interface ConnectorDescription { */ export function createConnector( connectorDesc: ConnectorDescription, -): >(Composed: React.ComponentType) => - ConnectedComponentClass; +): ( + (stateless: React.StatelessComponent>) => React.ComponentClass + ) & ( + >>(Composed: React.ComponentType) => + ConnectedComponentClass, TExposed> + ); // Utils export const HIGHLIGHT_TAGS: { diff --git a/types/react-instantsearch-core/react-instantsearch-core-tests.tsx b/types/react-instantsearch-core/react-instantsearch-core-tests.tsx index 25bb9ac0df..aa8f3e88ec 100644 --- a/types/react-instantsearch-core/react-instantsearch-core-tests.tsx +++ b/types/react-instantsearch-core/react-instantsearch-core-tests.tsx @@ -20,7 +20,8 @@ import { connectAutoComplete, Hit, TranslatableProvided, - translatable + translatable, + ConnectorProvided } from 'react-instantsearch-core'; () => { @@ -41,13 +42,7 @@ import { // https://community.algolia.com/react-instantsearch/guide/Custom_connectors.html () => { - interface Provided { - query: string; - page: string; - refine: (newQuery: string, newPage: number) => void; - } - - const CoolWidget = createConnector({ + const CoolWidget = createConnector({ displayName: 'CoolWidget', getProvidedProps(props, searchState) { @@ -73,9 +68,10 @@ import { queryAndPage: [newQuery, newPage], }; }, - })((props: Provided) => + })((props) =>
The query is {props.query}, the page is {props.page}. + This is an error: {props.somethingElse} { /* $ExpectError */} {/* Clicking on this button will update the searchState to: { @@ -102,6 +98,113 @@ import { ; }; +() => { + interface Provided { + query: string; + page: number; + } + + interface Exposed { + defaultRefinement: string; + startAtPage: number; + } + + const typedCoolConnector = createConnector({ + displayName: 'CoolWidget', + + getProvidedProps(props, searchState) { + // Since the `queryAndPage` searchState entry isn't necessarily defined, we need + // to default its value. + const [query, page] = searchState.queryAndPage || + [props.defaultRefinement, props.startAtPage]; + + // Connect the underlying component to the `queryAndPage` searchState entry. + return { + query, + page, + }; + }, + + refine(props, searchState, newQuery, newPage) { + // When the underlying component calls its `refine` prop, update the searchState + // with the new query and page. + return { + // `searchState` represents the search state of *all* widgets. We need to extend it + // instead of replacing it, otherwise other widgets will lose their + // respective state. + ...searchState, + queryAndPage: [newQuery, newPage], + }; + }, + }); + + const TypedCoolWidgetStateless = typedCoolConnector((props) => +
+ The query is {props.query}, the page is {props.page}. + This is an error: {props.somethingElse} { /* $ExpectError */} + {/* + Clicking on this button will update the searchState to: + { + ...otherSearchState, + query: 'algolia', + page: 20, + } + */} +
+ ); + + ; + + const TypedCoolWidget = typedCoolConnector( + class extends React.Component & { passThruName: string }> { + render() { + const props = this.props; + return
+ The query is {props.query}, the page is {props.page}. + The name is {props.passThruName} + {/* + Clicking on this button will update the searchState to: + { + ...otherSearchState, + query: 'algolia', + page: 20, + } + */} +
; + } + } + ); + + ; + +}; + () => { interface StateResultsProps { searchResults: SearchResults<{