Search Result Typing | Yext Hitchhikers Platform
Both Search UI React and Search Headless React are written fully in Typescript and provide intuitive typings for state, actions, and components. However, the library does not know ahead of time about the types of the entities in your Content.
Fortunately, the Yext CLI provides a command to generate Typescript types for your Search experience based on the structure of your Content. You can then use these types in your project via Typescript Generics , so that you get type safety and type hints for displaying results.
Download the Yext CLI and log into your Yext Account to use the command.
Generate Types
The following command will generate a different TypeScript file for each vertical in a Search experience. Each file contains interfaces for all entity types configured in the respective vertical. By default all files will be created in a types
folder.
yext types generate search [DESTINATION-DIR] [FLAG ...] [flags]
Flags:
--experienceKey string
: The experience key of your search experience (Required)-h, --help
: Help for search
For example, if you navigated to the src
folder in your project after running yext types generate search src/types --experienceKey doctor-search
, your project structure will look something like this:
my-app
βββ src
β βββ types
β β βββ faqs.ts
β β βββ doctors.ts
β βββ App.tsx
β βββ index.css
β βββ main.tsx
βββ .gitignore
βββ package-lock.json
βββ package.json
Each file in types
exports an interface for the entities returned by the vertical. For example:
export default interface Doctor {
id: string;
type: string;
address: Address;
specialty?: Specialty;
firstName: string;
gender: string;
geocodedCoordinate: GeocodedCoordinate;
headshot: Headshot;
languages?: string[];
lastName: string;
name: string;
uid: string;
}
export interface Address {
city: string;
line2: string;
countryCode: string;
region: string;
line1: string;
postalCode: string;
}
export interface Specialty {
name: string;
}
export interface GeocodedCoordinate {
longitude: number;
latitude: number;
}
export interface Headshot {
url: string;
height: number;
thumbnails?: Thumbnail[];
width: number;
}
export interface Thumbnail {
height: number;
url: string;
width: number;
}
Using Generated Types in Your Project
The generated Typescript types come in handy when using a custom CardComponent
in conjunction with the <VerticalResults />
and <UniversalResults />
components. Each of these will provide type safety based on the shape of the Search API response.
<VerticalResults />
and <UniversalResults />
with Custom Cards
If you are using Search UI React and are using one of these two components you can pass the generated type directly to the component as a generic. For vertical results, it looks like this:
import { useSearchActions } from "@yext/search-headless-react";
import {
SearchBar,
VerticalResults,
CardComponent,
CardProps,
} from "@yext/search-ui-react";
import { useEffect } from "react";
import { Doctor } from "./types/doctors";
const DoctorCard = ({
result,
}: CardProps<Doctor>): JSX.Element => {
const product = result.rawData;
return (
<div>
{/* Your Code Here */}
</div>
);
};
const App = (): JSX.Element => {
const searchActions = useSearchActions();
useEffect(() => {
searchActions.setVertical("doctors");
}, []);
return (
<div className="flex justify-center px-4 py-6">
<div className="w-full max-w-5xl">
<SearchBar />
<VerticalResults<Doctor> CardComponent={DoctorCard} />
</div>
</div>
);
}
export default App;
In this example, the DoctorCard
is type safe.
If you are working with universal results, this works similarly, except that you provide a map from vertical keys to generated types, like so:
import {
SearchBar,
UniversalResults,
} from "@yext/search-ui-react";
import { useEffect } from "react";
import { Faq } from "./types/faqs";
import { Product } from "./types/products";
// declare or import DoctorCard and FaqCard
interface VerticalTypeMap {
products: Product;
faqs: Faq;
}
const App = (): JSX.Element => {
return (
<div className="flex justify-center px-4 py-6">
<div className="w-full max-w-5xl">
<SearchBar />
<UniversalResults<VerticalTypeMap>
verticalConfigMap={{
products: { CardComponent: DoctorCard },
faqs: { CardComponent: FaqCard },
}}
/>
</div>
</div>
);
};
export default App;
This guarantees type-safety for all cards passed to the verticalConfigMap
.