How to return type based on generic input type?

Viewed 109

I'm working on a wrapper for fetch. I'd like to create a generic function for all CRUD (post, get, update, delete) operations. The GET request returns some data wheres a DELETE request might not return any data.

function fetchIt<T>(path: string, init?: RequestInit | undefined): T {
  // really use fetch
  // ...
  // if T is not provided return null
  //
  // if T is given return a value of type T

  return {} as T
}

interface User {
  name: string
}

// getResult should be of type User because we provided User as input type
const getResult = fetchIt<User>('/users/1')

// deleteResult should be null because we did not provide any input type
const deleteResult = fetchIt('/users')

Here is link to the playground.

I don't want to return T | null because then I always have to check whether the result is null or not.

// this is not what I want
function fetchThis<T>(): T | null {
  return null
}

const a = fetchThis()
const b = fetchThis<User>()

if (b !== null) {
  console.log(b)
}

I'd like to get null whenever I don't provide a generic type and whenever I provide a type it should be the return value.

Any ideas? Thank you very much!

1 Answers

You might want T itself to be null when it is not manually specified by the caller. If so, you can use a generic parameter default with the = syntax:

function fetchIt<T = null>(path: string, init?: RequestInit | undefined): T {
  return {} as T; // unsafe assertion, but so is fetch() I guess so ‍♂️
}

This gives you the behavior you're asking for:

const getResult = fetchIt<User>('/users/1');
// const getResult: User
const deleteResult = fetchIt('/users');
// const deleteResult: null

Playground link to code

Related