打字稿中的条件泛型类型

时间:2020-07-29 14:16:00

标签: typescript

想象一下,您有一个Foo接口,它会收到一个通用类型T,例如

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;
}

知道这是否有可能吗?

3 个答案:

答案 0 :(得分:3)

这应该有效

type Foo<T = undefined> = T extends undefined ? {} : {
   bar: T
}

const foo : Foo = { bar: "hello" }
const bar: Foo<string> = { bar: "hello" }
const foobar : Foo = {}

答案 1 :(得分: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

答案 2 :(得分:1)

您可以使用两个界面对其进行建模

interface FooBase {
  // all expext bar 
}

interface Foo<T> extends FooBase {
  bar: T
}

通过这种方式,接口FooBase包含始终需要的所有内容,并且Foo仅包含bar的内容,还可以强制执行FooBase声明的所有内容。