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
?
Code:
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')
CodePudding user response:
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.
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');