【问题标题】:Conditional generic types in typescript打字稿中的条件泛型类型
【发布时间】:2020-07-29 22:46:44
【问题描述】:

假设你有一个接收泛型类型 T 的 Foo 接口

interface Foo<T> {
  ...
  bar: T;
}

现在你希望 T 类型是可选的,所以你设置一个默认值

interface Foo<T = undefined> {
  ...
  bar: T;
}

但仍然需要“bar”。

如何在设置类型 T 时获取 'bar' 为必需(不是未定义),并在未设置类型 T 时将其删除(或将其设置为不需要)?

我已经尝试过类似下面几行的内容,但仍然需要“bar”。我可以在 'bar' 属性中添加一个问号,但设置 T 时将不需要 'bar'。

interface Foo<T = undefined> {
  ...
  bar: T extends undefined ? never : T;
}

知道这是否可能吗?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    这应该可以工作

    type Foo<T = undefined> = T extends undefined ? {} : {
       bar: T
    }
    
    const foo : Foo = { bar: "hello" }
    const bar: Foo<string> = { bar: "hello" }
    const foobar : Foo = {}
    

    【讨论】:

    • 不知道我解释得好不好,但在那种情况下,我仍然会收到错误 Property 'bar' is missing in type '{ ... }' but required in type 'Foo'.ts(2741)
    • 好的,我明白你在说什么。当 T 未设置时,您不希望它是必需的吗?
    • 完全正确,并且仅在未设置 T 时
    • 更新了我的答案
    • 如此接近,在提香回答几分钟后:) 不幸的是无法将两者标记为已接受。会投票,因为也是正确的
    【解决方案2】:

    取决于您为什么需要这个,基本和派生接口解决方案对于大多数情况都非常好(在此处的另一个答案中提供)。

    您不能使用条件类型将字段设为可选。但是您可以改用交集类型:

    type Foo<T = undefined> = {
      otherFields: string
    } & ([T] extends [undefined] ? {} : {
      bar: T
    })
    
    let x: Foo<undefined> = {
      otherFields: ""
    }
    
    let x2: Foo<string> = {
      otherFields: "",
      bar: ""
    }
    

    Playground Link

    【讨论】:

    • 将接口转换为类型,然后使用交叉接缝来完成任务!谢谢!我试图避免派生解决方案接口,因为对于多个泛型类型,我最终会为同一只海豚提供太多接口
    【解决方案3】:

    您可以使用两个接口对其进行建模

    interface FooBase {
      // all expext bar 
    }
    
    interface Foo<T> extends FooBase {
      bar: T
    }
    

    这样,接口FooBase 包含所有需要的东西,Foo 只包含bar,但也强制执行FooBase 声明的所有东西。

    【讨论】:

    • 这是一个解决方案,但不是真正的答案。我试图避免这种情况,因为我将有多个名称用于“相同”界面
    • 但实际上它不是同一个接口,接口的目的是授予文件、属性和方法的存在。而有条件地一个文件丢失的接口会产生完全不同的类型。
    • 是的,你是对的。可能应该为问题添加更多上下文。我不会直接使用该接口,这里的目标是基于该通用接口创建多种类型。在这种情况下,它们将用于 redux 操作,其中我将拥有多种类型,这些类型仅在字符串文字中有所不同,并且是否具有有效负载属性。使用 Titian 和 Todd 解决方案,我将能够仅通过接口声明来强制属性的存在,而不必将声明与接口名称结合起来。但对于更简单的情况,你的答案应该是去的那个
    猜你喜欢
    • 2021-11-09
    • 2021-11-26
    • 1970-01-01
    • 1970-01-01
    • 2019-08-11
    • 2019-05-03
    • 2020-05-09
    • 2020-06-29
    • 1970-01-01
    相关资源
    最近更新 更多