Dada a seguinte implementação de função:
function fmap<T, U>(value: T, f: (x: T) => U): U;
function fmap<T, U>(value: T | undefined, f: (x: T) => U): U | undefined;
function fmap<T, U>(value: T | null, f: (x: T) => U): U | null;
function fmap<T, U>(value: T | null | undefined, f: (x: T) => U): U | null | undefined {
return value === undefined ? undefined : value === null ? null : f(value);
}
Eu obtenho os tipos corretos nos seguintes casos:
const test1 = (v: string) => fmap(v, x => x); // ✅ expected: string
const test2 = (v: string | null) => fmap(v, x => x); // ✅ expected: string | null
const test3 = (v: string | undefined) => fmap(v, x => x); // ✅ expected: string | undefined
const test4 = (v: string | null | undefined) => fmap(v, x => x); // ✅ expected: string | null | undefined
const test5 = (v: string) => fmap(v, x => 1); // ✅ expected: number
Mas não nestes casos:
// ❌ expected: number | null (actual: number)
const test6 = (v: string | null) => fmap(v, x => 1);
// ❌ expected: number | undefined (actual: number)
const test7 = (v: string | undefined) => fmap(v, x => 1);
// ❌ expected: number | null | undefined (actual: number)
const test8 = (v: string | null | undefined) => fmap(v, x => 1);
Você precisará extrair tipos anuláveis do
T
tipo genérico