The title I wrote might be a bit complicated, so let me clarify my intentions below.
Imagine I have a specific type for a document that contains some data:
type Doc<TData extends {}> = {
data: TData;
}
In addition, there is a function where I can provide the document and an array of data properties:
declare function setData<TDoc extends Doc<{}>>(document: TDoc, keys: Array<keyof TDoc["data"]>): void;
Now, suppose I define the following types and constants based on them:
type PersonData = {
name: string;
address: string;
age: number;
nickname: string;
zipCode: string;
}
type PersonDoc = Doc<PersonData>;
declare const person: PersonDoc;
If I use the setData
function with the person object, the second parameter (keys
) would consist of the data properties, in this case:
Array<"name" | "address" | "age" | "nickname" | "zipCode">
This allows me to call the function like this:
setData(person, ["name", "age"]);
This informs TypeScript to strictly enforce those specified arguments.
However, here's the challenge I've been grappling with all day but haven't been successful in achieving yet. It seems like I might be stretching Typescript too thin.
Suppose I introduce a third argument to the setData
function, I want that third argument to be an object containing properties specified in the keys
argument, each associated with a unique type.
Here's a conceptual example (which doesn't work as intended):
type Definition = {
type: string;
isKey: boolean;
}
type OtherObject<T extends Array<string>> = {
[K in T[number]]: Definition;
}
declare function setData<TDoc extends Doc<{}>>(document: TDoc, keys: Array<keyof TDoc["data"]>, otherObject: OtherObject</* keys argument */>): void;
If I were to call the setData
function this time, the third argument otherObject
should take the following shape:
{
name: Definition;
address: Definition;
}
Therefore, it would look something like this:
setData(person, ["name", "age"], {
name: {
type: "something",
isKey: false
},
age: {
type: "something2"
isKey: false
}
});
If either name
or age
is missing in the object, TypeScript should flag it as an error.
This is my objective. Whether through a function or an object type like this:
type Options<TDoc extends Doc<{}>> = {
keys: Array<keyof TDoc["data"]>;
otherObject: OtherObject</* keys argument */>;
}
I'm open to either implementation. Despite my attempts without success, I haven't found any helpful information via Google searches. Seeking assistance on StackOverflow is my final option before giving up entirely.
Thank you in advance for your support.