I'm currently struggling to find the correct way to define this function in order for all four "tests" that come after it to pass. I've experimented with different function overloads and conditional types, but haven't fully grasped them yet. I even attempted to delve into the infer
concept, but unfortunately, it remains quite perplexing to me.
export function parse<T = unknown>(value: string | null): T {
// I'm stuck here ^
return typeof value === 'string' ? JSON.parse(value) : null
}
const a = parse<string>('"test"') // a is string
const b = parse<string>(null) // b is string, but it should be null
const c = parse('"test"') // c is unknown
const d = parse(null) // d is unknown, though it should be null
const json = window.localStorage.getItem('foobar')
const e = parse<string>(json) // e is string, but it should be string | null
I managed to rectify the typings for the first four cases using overloads:
export function parse<T = unknown>(value: string): T;
export function parse<T = unknown>(value: null): null;
export function parse<T = unknown>(value: string | null): T | null {
return typeof value === 'string' ? JSON.parse(value) : null;
}
const a = parse<string>('"test"') // a is string
const b = parse<string>(null) // b is null
const c = parse('"test"') // c is unknown
const d = parse(null) // d is null
However, this approach doesn't allow me to input a value that could be either a string
or null
, such as in the case of e
:
const json = window.localStorage.getItem('foobar') // json is string | null
const e = parse<string>(json)
// ^^^^ Error: No overload matches this call.
Is there a way to define the return type of the function that satisfies all of my "tests" and also permits passing a value that could be either, as illustrated in the example above?