Context:
I am working on an application, that generates filters for a GraphQL query dynamically.
To work with this generated filters, I am trying to create a Typescript type that resembles the allowed structure of these filters.
Issue:
The Typescript type I need, should allow every string as it's key, with type A as its value. Only certain keys (in this case, "AND" and "OR") should have a different type for their value.
Simplified Example:
The following example is simplified (while still complex enough):
The following filter Object should be allowed:
let filter = {
"fieldA": "2015-10-08",
"fieldB": "This is the search input string...",
OR: [
{"fieldC1": "deleted"},
{ AND: [
{"fieldD": "null"},
{"fieldE": "inactive"}
]}
],
}
After some search () and reading the docs I came up with this type:
type CustomTypeBase = {
[key: string]: string;
} & {
AND?: Array<{[key: string]: string} | CustomTypeBase>;
OR?: Array<{[key: string]: string} | CustomTypeBase>;
};
This does not work, sadly, as Typescript wants EVERY string-key (including "AND" and "OR) to hold a string value.
I tried to fix this problem with:
type CustomTypeWithOmit = Omit<{
[key: string]: string;
}, 'AND' | 'OR'> & {
AND?: Array<{[key: string]: string} | CustomTypeWithOmit>;
OR?: Array<{[key: string]: string} | CustomTypeWithOmit>;
};
But this does not work either, as the Omit utility type does not work on general types like string, but only works on specific types.
Question:
Is there any way to have a typescript type, that allows type A for all string keys and type B only for certain string keys?
TS Playground link:
Code on TS Playground
ANDandORproperties are both optional, so there's{}is assignable to both types in the union, you don't get excess property warnings like you normally do. But it's still not the right type, because you can assign surprisingly wrong things to it as shown in this playground link. I guess it's a possible workaround for all-optional types, though.