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 Knowledge Graph.
Fortunately, the Yext CLI provides a command to generate TypeScript types for your Search experience based on the structure of your Knowledge Graph. 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, after running yext types generate search src/types --experienceKey doctor-search from the src folder, 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 are most useful when using a custom CardComponent with the <VerticalResults /> and <UniversalResults /> components, providing type safety based on the shape of the Search API response.
<VerticalResults /> with a Custom Card
Pass the generated type directly to the component as a generic:
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, DoctorCard is type safe.
<UniversalResults /> with Custom Cards
For universal results, provide a map from vertical keys to generated types:
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.