Home > Mobile >  Constraining output to not be undefined if input parameter is definitely not undefined
Constraining output to not be undefined if input parameter is definitely not undefined

Time:04-11

I have a function like

const toString = (date?: Date) => date?.toString();

Which I would like typecheck to (Date) => string when given a Date but to (Date | undefined) => string | undefined when given Date | undefined or undefined.

I have tried something like this in a number of different ways:

type Verify<T, D> = T extends undefined ? D | undefined : D;

const dateToString = <T extends Date | undefined>(date: Verify<T, Date>) => {
    if (date === undefined) {
        return undefined as Verify<T, string>;
    }
    return date.toString() as Verify<T, string>;
};

const a = dateToString(new Date(23));
const b = dateToString(undefined as Date | undefined);
const c = dateToString(undefined);

But I cannot seem to get the behavior I want, either everything typechecks to (Date | undefined) => string or (Date) => string. Apparently I do not grok typescript generics with constraints.

A proper name for this helper constraining type would also be appreciated.

CodePudding user response:

How about using a function overload...

function dateToString(date: Date): string;
function dateToString(date?: Date): string | undefined ;
function dateToString(date?: Date): string | undefined {
    if (date === undefined) {
        return undefined;
    }
    return date.toString();
}

const x = dateToString(new Date()); // x: string
const y = dateToString();           // y: string | undefined

CodePudding user response:

type Verify<T, D> = T extends undefined ? D | undefined : D;

const dateToString = <T extends Date | undefined>(date: T): Verify<T, string> => {
    if (date === undefined) {
        return undefined as Verify<T, string>;
    }
    return date.toString();
};

const a = dateToString(new Date());                    // const a: string
const b = dateToString(undefined as Date | undefined); // const b: string | undefined
const c = dateToString(undefined);                     // const c: string | undefined
  • Related