typescript - Typannotation för funktion med nullspridning


I detta scenario har vi en funktion som formaterar ett datum, men som också sprider nullvärden:

function DateToIso(d: Date | null) {
    return d === null ? null : SugarDate.format(d, '%F');
}

Jag skulle vilja kunna anropa den här funktionen och få returtypen att matcha nullbarheten hos den angivna parametern. Till exempel fungerar inte detta - men det borde göra det i min lilla lyckliga värld.

const nowIso: string = DateToIso(new Date());

Hur kan jag specificera funktionen så att det ovanstående fungerar, samtidigt som spridning av null-värden fortfarande tillåts?

Svar #1

Du behöver bara använda överlagringar:

function DateToIso(d: Date): string;
function DateToIso(d: null): null;
function DateToIso(d: Date | null):string | null {
    return d === null ? null : d.toISOString();
}

const withNull = DateToIso(null); // null
const withString = DateToIso(new Date()); // string

Dokument

Lekplats

Förresten, du behöver inte använda explicita typer här const nowIso: string=DateToIso(new Date());. TS kan i de flesta fall härleda det

Svar #2

Det verkar som att förslaget att använda överlagringar inte garanterar null-säkerhet. Jag föreslår att använda två olika funktioner och anropa den motsvarande beroende på sammanhang:

function DateToIso(d: Date) {
    return SugarDate.format(d, '%F');
}

function DateToIsoNullalbe(d: Date | null) {
    return d === null ? null : DateToIso(d);
}

Kanske bestämmer du dig för att använda en wrapper för att höja vilken icke-nullbar funktion som helst till nullable. Något som

function wrapNullable<T, R>(f: (t: T) => R): (t: T | null) => (R | null) {
    return t => t === null ? null : f(t);
}

Så du skulle kunna göra wrapNullable(DateToIso)(xxx)

Lekplatslänk

Jag antar att det är ännu bättre eftersom det inte har någon null-kontroll när det är känt att du inte behöver dem. Kan förbättra prestanda... åtminstone teoretiskt.