I have a use-case where an external query returns an object with a property with the same name as one of my interfaces. As you can see in the sample executeQuery function, if I pass in "message" as a query, then I will be returned an object with 1 property named "Message".
I want to be able to create a generic interface of T that has 1 property where the name is the name of T and the type is T.
I understand there are run-time solutions to this, but I was wondering if this was possible using only Typescript types at compile time.
shared code:
function executeQuery<T>(query: "message" | "mailbox") {
const data = query === "message" ?
{ Message: { id: 1 } } as unknown as T :
{ Mailbox: { id: 2 } } as unknown as T
return { data: data }
}
interface Message {
id: number
}
interface Mailbox {
id: number
}
1st solution:
interface AllContainer {
Message: Message
Mailbox: Mailbox
}
const messageQueryResult = executeQuery<AllContainer>("message")
console.log(messageQueryResult.data.Message.id)
const mailboxQueryResult = executeQuery<AllContainer>("mailbox")
console.log(mailboxQueryResult.data.Mailbox.id)
2nd solution:
interface MessageContainer {
Message: Message
}
interface MailboxContainer {
Mailbox: Mailbox
}
const messageQueryResult2 = executeQuery<MessageContainer>("message")
console.log(messageQueryResult2.data.Message.id)
const mailboxQueryResult2 = executeQuery<MailboxContainer>("mailbox")
console.log(mailboxQueryResult2.data.Mailbox.id)
What I want to be able to do:
interface GenericContainer<T> {
[T.Name]: T // invalid Typescript
}
const messageQueryResult3 = executeQuery<GenericContainer<Message>>("message")
console.log(messageQueryResult3.data.Message.id)
const mailboxQueryResult3 = executeQuery<GenericContainer<Mailbox>>("mailbox")
console.log(mailboxQueryResult3.data.Mailbox.id)