I am quite new to typescript and I am not sure if this is achievable or not.
Basically, I have some fetched data with known types (some queries to database) and I want to store them in a predefined variable so I can pass it around (a context in my use case). However, the data type changes base on the query parameters. I am storing the data inside the variable with type any but the intellisense would be lost.
// file A.ts
export const someContext : { fetchedData: any } = { fetchedData: null }
// file B.ts
import { someContext } from "A"
...
const data = await fetchData("some api and queries")
// data can be {id: string, posts: number} or {id: string, lastLogin: Date} etc
// but the type is known
someContext.fetchedData = data; // there is no intellisense for fetchedData
My question is can I store the data in only one variable while preserving type intellisense.
One solution I thought of is to create a type of all possible fields of the fetched data (based on the database structure), and mark every field as optional but this is quite complicated and I need to update it everytime I change the db structure and I want to know if there is a way without statically setting the types. Ideally, I would want it to work with nested objects as well.
type fetchedDataTypes = {
id?: number; // statically setting types
lastLogin?: Date;
posts?: number;
...
}
const someContext : { fetchedData: fetchedDataTypes } = { fetchedData : {} }
EDIT:
For some more context, I am doing something similar to an API call from client to server, and the context is created from the server side and is passed around to different components that is run from the client side, so any data passed into it will persist and can be used across the whole app. The syntax is of course different base on the framework used, but one example similar is nextjs + tRPC, where the end-points for the api calls are typesafe, and I want to find a way to store the data from the api calls without losing the type intellisense, and also without statically setting the types in prior.
A minimal reproducible example using react here.
2
Answers
If you know for sure what your
fetch()
call will return, you can use generics and Type Assertion to enforce certain return types that will give you intellisense. I’d recommend to defineFetchedData
as a Union Type instead of optional properties because there’s a difference between a property of valueundefined
and a property that is not there at all.However, you’ll need to be really careful about that since you can trick yourself very easily. In the example below
fetchMock
will always return{posts: 42}
. The return type will only be based on the generic argument.TypeScript Playground
The most straightforward way would be
If you need to create your object before, you may still use the type of data variable: