Search code examples
typescripttypescript-generics

Inferring different types based on null value in Typescript


I want to be able to infer different types based on whether the value of a parameter is null or not. Here is what I have:

import { Message } from "@bufbuild/protobuf";

export type Result<T extends Message> = { data: T | null };

export async function sendRequest<T extends Message>(
  responseConstructor: (new () => T) | null
): Promise<Result<T>> {
  if (!responseConstructor) {
    return { data: null };
  }

  return { data: new responseConstructor() };
}

This partially works, but when I pass a value to responseConstructor, it still shows the possibility of null value in the Result. I want the Result to be {} if responseConstructor is null, and { data: T } if it is not.

How can I achieve this?


Solution

  • Use function overloads.

    Note: instead of { data: null }, Record<keyof any, never> means {}.

    import { Message } from "@bufbuild/protobuf";
    
    export type Result<T extends Message> = { data: T }
    
    export async function sendRequest(responseConstructor: null): Promise<Record<keyof any, never>>
    export async function sendRequest<T extends Message>(responseConstructor: (new () => T)): Promise<Result<T>>
    
    export async function sendRequest<T extends Message>(
      responseConstructor: (new () => T) | null
    ): Promise<Result<T> | Record<keyof any, never>> {
      if (!responseConstructor) {
        return {};
      }
    
      return { data: new responseConstructor() };
    }