1

How can I properly type the return type of the following function without using any? It's a function that, depending on the presence of one parameter, returns a string or a function.

function useFetchResource(resourceType: string, id?: string): string {
    if (id) {
        return `${resourceType}:${id}`; 
    } else {
        // ERROR HERE
        return (innerId: string) => {
            return `${resourceType}:${innerId}`;
        };
    }
}

useFetchResource("products", "10");
const fetchProduct = useFetchResource("products");
// ERROR HERE
fetchProduct("10");

I've tried using overload without success:

function useFetchResource(resourceType: string): ((id: string) => string); // COMPILE ERROR: Incompatible implementation
function useFetchResource(resourceType: string, id?: string): string {

After a while, and many failed attempts to understand and use more advanced concepts, I tried the same with a function that could return just a number or a string if one parameter was present, and it failed in the same way:

function useFetchResource(resourceType: string): number; // COMPILE ERROR: Incompatible implementation
function useFetchResource(resourceType: string, id?: string): string {
    if (id) {
        return `${resourceType}:${id}`; 
    } else {
        return 1;
    }
}

I've also tried using a union type of string | ((id: string) => string) but it forced the consumer of the function to cast the value in order to use it: (fetchProduct as ((id: string) => string))("10"), which wasn't what I tried to accomplish.

Is doing something like that possible in typescript?

1 Answers1

3

You have to define both overloads and implementation of the function.

function useFetchResource(resourceType: string): (id: string) => string;
function useFetchResource(resourceType: string, id: string): string;
function useFetchResource(resourceType: string, id?: string): string | ((id: string) => string) {
    if (id) {
        return `${resourceType}:${id}`; 
    } else {
        // ERROR HERE
        return (innerId: string) => {
            return `${resourceType}:${innerId}`;
        };
    }
}

const key = useFetchResource("products", "10");
const fetchFunction = useFetchResource("products");

// No ERROR HERE
fetchFunction("10");
Nenad
  • 24,809
  • 11
  • 75
  • 93