jss icon indicating copy to clipboard operation
jss copied to clipboard

Add TypeScript generics support for useSitecoreContext hook

Open thaiphan opened this issue 3 years ago • 0 comments

Description

I'm using using the useSitecoreContext hook like so...

const {sitecoreContext} = useSitecoreContext();

// This returns GenericFieldValue
const pageTitle = sitecoreContext.route.fields.pageTitle

Unfortunately, GenericFieldValue is too general of a type. I would prefer to be more specific.

Expected behavior

I would like to able to do the following:

interface DashboardFields {
    pageTitle: Field<string>;
}

const {sitecoreContext} = useSitecoreContext<DashboardFields>();

// This returns Field<string>
const pageTitle = sitecoreContext.route.fields.pageTitle

Possible Fix

I'm currently using Module Augmentation in order to support my current scenario:

declare module '@sitecore-jss/sitecore-jss-react' {
  function useSitecoreContext<T = RouteData['fields']>(
    options?: WithSitecoreContextOptions,
  ): {
    sitecoreContext: SitecoreContextValue<T>;
    updateSitecoreContext: (
      value: import('@sitecore-jss/sitecore-jss/layout').LayoutServiceData | SitecoreContextValue<T>,
    ) => void;
  };
}

export declare type SitecoreContextValue<T = Record<string, Field>> = LayoutServiceContext & {
    itemId?: string;
    route?: RouteData<T>;
};

export interface RouteData<T = Record<string, Field>> {
    name: string;
    displayName?: string;
    fields?: T;
    databaseName?: string;
    deviceId?: string;
    itemLanguage?: string;
    itemVersion?: number;
    layoutId?: string;
    templateId?: string;
    templateName?: string;
    placeholders: PlaceholdersData;
    itemId?: string;
}

However, I would prefer if you guys added support for generics.

export declare function useSitecoreContext<T = Record<string, Field>>(options?: WithSitecoreContextOptions): {
    sitecoreContext: SitecoreContextValue<T>;
    updateSitecoreContext: (value: import("@sitecore-jss/sitecore-jss/layout").LayoutServiceData | SitecoreContextValue<T>) => void;
};

export declare type SitecoreContextValue<T = Record<string, Field>> = LayoutServiceContext & {
    itemId?: string;
    route?: RouteData<T>;
};

export interface RouteData<T = Record<string, Field>> {
    name: string;
    displayName?: string;
    //fields?: {
    //    [name: string]: Field;
    //};
    fields?: T;
    databaseName?: string;
    deviceId?: string;
    itemLanguage?: string;
    itemVersion?: number;
    layoutId?: string;
    templateId?: string;
    templateName?: string;
    placeholders: PlaceholdersData;
    itemId?: string;
}

thaiphan avatar May 12 '22 08:05 thaiphan