如何根据参数类型推断返回类型

时间:2019-12-19 22:41:14

标签: typescript generics

我试图弄清楚如何键入此函数,以便在其运行后进行四个“测试”。我一直在尝试函数重载和条件类型(我不太了解)的各种组合,并尝试研究infer(我真的不了解),但是我似乎无法弄清楚。

export function parse<T = unknown>(value: string | null): T {
                     // Can't figure out what to put 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 should be null
const c = parse('"test"')         // c is unknown
const d = parse(null)             // d is unknown, but should be null

const json = window.localStorage.getItem('foobar')
const e = parse<string>(json)     // e is string, but should be string | null

以下使用重载纠正了前4种情况的输入:

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

但是不允许我传递可能是string null的值,例如e

const json = window.localStorage.getItem('foobar') // json is string | null
const e = parse<string>(json)
                     // ^^^^ Error: No overload matches this call.

如何通过同时通过我的四个“测试”的方式键入函数的返回类型 ,它使我可以传递一个可以是上述任意一个的值?

1 个答案:

答案 0 :(得分:0)

您仅声明2个重载:

export function parse<T = unknown>(value: string): T;
export function parse<T = unknown>(value: null): null;

不是3,因为下一行是函数实现:

export function parse<T = unknown>(value: string | null): T | null { ... }

因此,您可以使用parse stringvalue null来调用此value函数,但不能使用可能是{{1 }},即string | null返回的结果。

因此,基本上,您只是缺少了一个重载,它实际上与实现的签名相匹配:

window.localStorage.getItem(...)

在这里您可以看到所有3个重载都在起作用:

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;
export function parse<T = unknown>(value: string | null): T | null {
  return typeof value === 'string' ? JSON.parse(value) : null;
}