[SOLVED] How to force generic type param to conform to a certain signature


I want to put a <T extends JsonRequest> on a function signature to force any interfaces to be serializable.

The error I get when trying this is:

Type 'AlertHistoryResponse' does not satisfy the constraint 'JsonRequest'.
  Type 'AlertHistoryResponse' is not assignable to type 'JsonObject'.
    Index signature for type 'string' is missing in type 'AlertHistoryResponse'.(2344)

I don’t want to add an index signature to AlertHistoryResponse though; is there any way I can assert AlertHistoryResponse is a JsonRequest?


type JsonPrimitive = string | number | boolean | null;
type JsonObject = {
    [key: string]: JsonRequest | undefined  // allow undefined here because these keys will be stripped when stringified
type JsonMap = Map<string, JsonRequest>  // will be converted into an object
type JsonArray = Array<JsonRequest>;
type JsonSet = Set<JsonPrimitive>  // will be converted into an array

 * Represents an object that can be serialized with jsonStringify() (not the native JSON.stringify)
export type JsonRequest = JsonPrimitive | JsonObject | JsonArray | JsonSet | JsonMap

function createGetQuery<T extends JsonRequest>(route: string) {
    return null

interface AlertHistoryEntry {
    id: string,
    segmentNumber: number
    alert: string
    dateUtc: string
    user: string

interface AlertHistoryResponse {
    log: AlertHistoryEntry[]
    timezone?: string

export const useAlertHistoryQuery = createGetQuery<AlertHistoryResponse>('bookings.getAlertHistory')



An interface won’t satisfy the index signature requirement because it can have new fields added to it (open). Use a type alias instead (closed). See Differences Between Type Aliases and Interfaces in the TS handbook.

TS Playground

type JsonSerializable = boolean | number | null | string | JsonSerializable[] | { [key: string]: JsonSerializable; };

type JsonMap = Map<string, JsonSerializable>  // will be converted into an object
type JsonSet = Set<JsonSerializable>  // will be converted into an array

type Serializable = JsonSerializable | JsonMap | JsonSet;

function createGetQuery <T extends Serializable>(route: string) {
  return null;

type AlertHistoryEntry = {
  id: string;
  segmentNumber: number;
  alert: string;
  dateUtc: string;
  user: string;

type AlertHistoryResponse = {
  log: AlertHistoryEntry[];
  timezone?: string;

const useAlertHistoryQuery = createGetQuery<AlertHistoryResponse>('bookings.getAlertHistory');

Answered By – jsejcksn

Answer Checked By – Senaida (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *