0

So I want to write some functions that accept a generic type T that can be any plain old javascript object, but nothing else. No class instances or functions or stuff like that. Basically, anything that could be serialized to string and then parsed back again using JSON.stringify() and JSON.parse() without losing any information.

I thought I could do that like this:

type Primitive = number|string|boolean|bigint|symbol|undefined|null

export interface PlainObject {
  [key: string]: Primitive|Primitive[]|PlainObject|PlainObject[]
}

// Let's say that this is an example
// of a more specific type that I want to use.
interface User {
  id: number
  name: string
  age: number
}

async function fetchFromApi<T extends PlainObject>(url: string): Promise<T> {
  // ...
}

Now I was hoping that I could then do this:

const user = await fetchFromApi<User>("/users/1")

But Typescript complains. And I understand the complaint. The User type is much more restrained than the PlainObject type, because User doesn't allow for just any key to be set.

But I don't know how else to express in code:

"I want this generic type T to be constrained to be a POJO, but otherwise it may have any narrower type than that."

Can anybody tell me how I can express that in TypeScript?

Evert
  • 2,022
  • 1
  • 20
  • 29
  • "Type[S]cript complains" about what? – Thomas Aug 04 '22 at 08:08
  • 1
    I wonder if you could just use `T extends Object` instead of using your PlainObject type. Also, the return type of your function is `Promise` and not just `T` – nook Aug 04 '22 at 08:14
  • @TobiasS. yes, I actually just stumbled upon an article that gave the same answer(s). So yes I'm now converting all my interfaces to type aliases. I just wonder if maybe then I will come across a downside of using type aliases. – Evert Aug 04 '22 at 08:17

0 Answers0