APixel Visuals
APixel Visuals

Reputation: 1648

TypeScript - Function return type based on multiple parameters

I'm creating a function that exports an image. It needs to take the format, exportType and pathOrWithMetadata parameters. I have the following code:

interface ExportMetadata {
    data: Buffer;
    width: number;
    height: number;
}

export type Format = "png" | "jpeg";

export type ExportTypes = "file" | "buffer";

export type Output<ExportType> = ExportType extends "file" ? undefined : Buffer;

export default async function exportTo<ExportType extends ExportTypes>(
    image: Image,
    format: Format,
    exportType: ExportType,
    pathOrWithMetadata?: string | boolean
): Promise<Output<ExportType>> { ... }

This will ensure that if the exportType is "file", undefined will be returned. But if the exportType is "Buffer", a Buffer will be returned. Now, I need the Buffer return type to be dependent on the pathOrWithMetadata parameter. Firstly, if the exportType is "file", pathOrWithMetadata must be a string. If the exportType is "buffer", it needs to be a boolean. If the boolean is true, the return type needs to be ExportMetadata. If it's false or undefined, it needs to return a Buffer.

Here's what I tried:

interface ExportMetadata {
    data: Buffer;
    width: number;
    height: number;
}

export type Format = "png" | "jpeg";

export type ExportTypes = "file" | "buffer";

export type PathOrWithMetadataOptions = string | boolean;

export type Output<ExportType, PathOrWithMetadata> = ExportType extends "file" ? undefined : (PathOrWithMetadata extends true ? ExportMetadata : Buffer);

export default async function exportTo<ExportType extends ExportTypes, PathOrWithMetadata extends PathOrWithMetadataOptions>(
    image: Image,
    format: Format,
    exportType: ExportType,
    pathOrWithMetadata?: PathOrWithMetadata
): Promise<Output<ExportType, PathOrWithMetadata>> { ... }

This worked for the following use cases:

exportTo(image, "png", "file", "example.png"); // Promise<undefined>
exportTo(image, "png", "buffer", true); // Promise<ExportMetadata>
exportTo(image, "png", "buffer", false); // Promise<Buffer>

But didn't work when pathOrWithMetadata is undefined:

exportTo(image, "png", "buffer");

The return type here is Promise<ExportMetadata | Buffer>. How can I have the return type be Promise<Buffer>?

Upvotes: 1

Views: 291

Answers (1)

APixel Visuals
APixel Visuals

Reputation: 1648

I found the solution to be to set a default value for the PathOrWithMetadata like so:

export default async function exportTo<ExportType extends ExportTypes, PathOrWithMetadata extends PathOrWithMetadataOptions = false>(...): Promise<Output<ExportType, PathOrWithMetadata>> { ... }

Upvotes: 1

Related Questions