Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define a JSON-compatible parameter to avoid error "Index signature is missing"?

I've got a function defined as:

export function useSubmitHandler(url: string, data: Json): [FormEventHandler<HTMLFormElement>, boolean] {}

Where Json is:

type JsonPrimitive = string | number | boolean | null | undefined
interface JsonMap extends Record<string, JsonPrimitive | JsonArray | JsonMap> {}
interface JsonArray extends Array<JsonPrimitive | JsonArray | JsonMap> {}
export type Json = JsonPrimitive | JsonMap | JsonArray

If I try to call it with an arbitrary interface though, I get an error:

TS2345: Argument of type 'Fee' is not assignable to parameter of type 'Json'.   
Type 'Fee' is not assignable to type 'JsonMap'.     
Index signature is missing in type 'Fee'

enter image description here

But if I call it with that same object but spread like {...store.data} then the error goes away.

How can I type useSubmitHandler properly so that it will accept any object that is JSON stringifyable?

I think the Json type is correct, but it needs something more to allow passing arbitrary types into the function.


Fee is:

interface Fee {
    id: number|null;
    name: string;
    type: string;
    amount: string;
    default: number;
    company_id: number;
    deleted_at?: any;
    active: number;
    fee_or_discount: string;
}

Of course, I'd like this to work with any type.

like image 506
mpen Avatar asked Sep 13 '25 18:09

mpen


1 Answers

Option 1: Redefine Json type

type JsonPrimitive = string | number | boolean | null;
type JsonMap = {
    [key: string]: JsonPrimitive | JsonMap | JsonArray;
}
type JsonArray = Array<JsonPrimitive | JsonMap | JsonArray>;
type Json = JsonPrimitive | JsonMap | JsonArray;

Option 2: Add an index signature to the Fee interface

interface Fee {
    [property: string]: any;
    id: number|null;
    name: string;
    type: string;
    amount: string;
    default: number;
    company_id: number;
    deleted_at?: any;
    active: number;
    fee_or_discount: string;
}

Option 3: Add an inline type assertion for the index signature, such as:

useSubmitHandler(Router.route('fees.store')!, store.data as {[property: string]: any})

See also

TypeScript GitHub issue Please provide a json basic type #1897

like image 94
Christopher Peisert Avatar answered Sep 16 '25 07:09

Christopher Peisert