question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Dynamically type the data result of a hook according to inputs

See original GitHub issue

Hey, folks!

We ran into a hiccup with trying to dynamically type the data that comes back from our endpoint.

Imagine an identity endpoint that can return either a string or a number:

// I recognize that you probably wouldn't do actually want to do this
// This is only an example to setup for our more complex real world example

const router = createRouter().query("foo", {
    input: z.enum(["string", "number"]),
	resolve: async ({input}) => {
		const pickEm = {
			string "test",
			number: 42
		}

		return pickEm[input]
	}
})

Now, when we go to use this on the frontend:

const query = trpc.useQuery(["foo", "string"])
query.data // Inferred type is number | string | undefined
// I would love for this hook have an inferred type of string

const query = trpc.useQuery(["foo", "number"])
query.data // Inferred type is number | string | undefined
// I would love for this hook have an inferred type of number

That’s my simple, silly example to demonstrate the idea of what we’re after. In the real world, what we are running into is this:

// trials/get is an endpoint that takes inputs for Prisma includes or selects for the Trial model
const query = trpc.useQuery(["trials/get", { select: { judgeName: true } } ])
query.data // Has no idea about the select, simply types for the whole Trial model

And here is our custom hook that we hacked together to resolve our problem.


export const useTrial = <T extends Prisma.TrialSelect>({
	trialId,
	select
}: {
	trialId: string
	select: Prisma.Subset<T, Prisma.TrialSelect>
}) => {
	type DataPayload = Prisma.TrialGetPayload<{ select: typeof select }>

	const query = trpc.useQuery(["trials/get", { id: trialId, select }])

	const queryDataTypeFix = query.data as Prisma.TrialSelect

	// Fix the data with itself but typed as what we want
	query.data = queryDataTypeFix

	return query as
		| Omit<typeof query, "data"> & {
				data: DataPayload
		  }
}

This seems to work well enough to get the types right. But I was surprised there wasn’t a more tRPC-ish way (that we could figure out).

100% am willing to contribute if there is a way we think we can do this - although I can’t say I’ll be too useful actually making the types happen. The TS you guys have drawn up is pretty opaque to me. 🙃

I know with v10 coming, we could be allowed to make some major change if needed to make this reality.

tRPC for life, yo! Keep it up!

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
anthonyshewcommented, Jul 10, 2022

Great minds thinking alike.

@mmkal I’d agree that that doesn’t seem like something we would want to get into for this.

@sachinraja I did notice that generic…But we had no idea what to do with it or if it was going to fit what we wanted to do. The inspiration for this idea came from react-query where you can do:

const query = useQuery<number>( )
query.data // Now it's a number

const query = useQuery<string>( )
query.data // Now it's a string

Maybe that is what that generic does and we just didn’t spend enough time fussing with it to find out? If it is, I’d be happy to add to the docs to make this clear for others.

Of course, tRPC is much different than react-query - but it’s API here is quite simple to use for getting whatever type you want. Wondering if we could accomplish something similar. 🤔

1reaction
sachinrajacommented, Jul 10, 2022

I’m thinking any sort of generic solution might be impossible because of https://github.com/microsoft/TypeScript/issues/1213 (“Higher Kinded Types”). tRPC already takes in a generic for the function.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Dynamically type the data result of a hook according to inputs
Collaborator. Hey, folks! We ran into a hiccup with trying to dynamically type the data that comes back from our endpoint. That's my...
Read more >
How to dynamically update the value for any input field with ...
How to dynamically update the value for any input field with one event handler function, using hooks ; const [email, setEmail] = useState...
Read more >
Creating Dynamic Forms With React Hooks - Aaron Powell
Dynamically generating forms can be a challenge, so let's break down how to do it with React Hooks.
Read more >
Create Dynamic Forms in React Using React Hook Forms
This article is about creating dynamic forms in React using React Hook Form and performing validation on data entered in form fields.
Read more >
Add and Remove Form fields dynamically with React and ...
Add and Remove Form fields dynamically with React and React Hooks. In this article, we will learn how we can add and remove...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found