【问题标题】:How to return type based on generic input type?如何根据泛型输入类型返回类型?
【发布时间】:2021-09-30 01:02:04
【问题描述】:

我正在为fetch 开发一个包装器。我想为所有 CRUD(发布、获取、更新、删除)操作创建一个通用函数。 GET 请求返回一些数据,而 DELETE 请求可能不会返回任何数据。

function fetchIt<T>(path: string, init?: RequestInit | undefined): T {
  // really use fetch
  // ...
  // if T is not provided return null
  //
  // if T is given return a value of type T

  return {} as T
}

interface User {
  name: string
}

// getResult should be of type User because we provided User as input type
const getResult = fetchIt<User>('/users/1')

// deleteResult should be null because we did not provide any input type
const deleteResult = fetchIt('/users')

这是playground的链接。

我不想返回T | null,因为那样我总是要检查结果是否为空。

// this is not what I want
function fetchThis<T>(): T | null {
  return null
}

const a = fetchThis()
const b = fetchThis<User>()

if (b !== null) {
  console.log(b)
}

每当我不提供泛型类型时,我都想获得null,而每当我提供类型时,它应该是返回值。

有什么想法吗?非常感谢!

【问题讨论】:

    标签: typescript typescript-generics


    【解决方案1】:

    当调用者未手动指定 T 时,您可能希望它本身为 null。如果是这样,您可以使用 generic parameter default= 语法:

    function fetchIt<T = null>(path: string, init?: RequestInit | undefined): T {
      return {} as T; // unsafe assertion, but so is fetch() I guess so ?‍♂️
    }
    

    这为您提供了您要求的行为:

    const getResult = fetchIt<User>('/users/1');
    // const getResult: User
    const deleteResult = fetchIt('/users');
    // const deleteResult: null
    

    Playground link to code

    【讨论】:

    • 我喜欢这样,但我不知道通用参数默认值。但是,当我实际返回 null 时,TypeScript 会抱怨。
    • 如果您要返回null (example),只需返回null as T。可能有可能跳过箍以获得编译器可以更安全的东西,但fetch() 是完全类型不安全的,无论如何都相当于类型断言,所以我不明白这一点。 (例如,如果您调用fetchIt&lt;A&gt;("url")fetchIt&lt;B&gt;("url"),它们在运行时都只是fetchIt("url"),所以AB 只是可能是错误的断言。
    • 我理解你的例子,但我不能直接返回null (example)。我必须做return null as unknown as T之类的事情吗?
    • 是的,你可以写null as unknown as T。如果这两种类型看起来“不够相关”,编译器会尝试警告断言,但这是一种启发式方法,您可以通过像 unknownanynull | T 这样的中间类型来处理它编译器认为与nullT 相关。
    猜你喜欢
    • 2016-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多