【问题标题】:How to avoid repeating generic type constraints with every usage in Typescript?如何避免在 Typescript 中的每次使用都重复泛型类型约束?
【发布时间】:2020-09-17 04:25:42
【问题描述】:

在 Typescript 中使用泛型时如何避免不断重复类型?如果我对泛型类型有一些约束,那么我必须在使用泛型类型的任何地方重复该约束。这很乏味,而且不是很干。

//A constraint on this generic
type MyConstraint = { bar: number }
type GenericOne<T extends MyConstraint> = {
    foo: T
}

要创建一个实例,我不得不重复约束,因为 TS 只对函数进行泛型推断

//This annoyance would I think be solved by generic values https://github.com/microsoft/TypeScript/issues/17574
const testok: GenericOne<MyConstraint> = { foo: { bar: 1 } }

现在,如果我想在其他地方使用我的泛型类型,我还必须重复约束!

const makeGenericOne2: <T extends MyConstraint>(arg: GenericOne<T>) => GenericOne<T> = (arg) => {
    return arg
}

至少现在我可以从对象字面量创建而无需重复自己

const test5 = makeGenericOne2({ foo: { bar: 1 } })
// And I get nice error messsages
const test6 = makeGenericOne2({foo: {baz: 1}})

避免重复约束的唯一方法似乎是带有推理的条件类型

const makeGenericOne: <T>(arg: T extends GenericOne<infer U> ? T : never) => T = (arg) => {
    return arg
}

我仍然可以从对象字面量创建实例而无需重复自己

const test3 = makeGenericOne({ foo: { bar: 1 } })

但现在错误消息不是那么好。

//"number not assignable to never" instead of { baz: 1 } is missing property "bar: number"
const test4 = makeGenericOne({ foo: { baz: 1 } })

似乎需要以下内容——推断 T,因为我们知道它必须扩展 Myconstraint

const propagateGeneric: <infer T>(arg: GenericOne<T>) => GenericOne<T>

很遗憾,目前 TS 不允许这样做。

我如何“传播”泛型类型的约束以避免在使用泛型类型的任何地方重复它?

Sandbox Link

【问题讨论】:

  • makeGenericOne 的功能到底是什么?我可能遗漏了一些东西,但问题并不太清楚
  • 如果你在第一个函数中省略了extends MyConstraint,你至少会得到一个有用的错误Type 'T' does not satisfy the constraint 'MyConstraint'. 所以即使你在那里重复自己,如果它不匹配它就不会编译,所以这一切都保持类型安全,以防您重构并忘记在两个地方进行更改。因此,在实践中,这并不是一个真正的问题,即使在大型代码库中也是如此。

标签: typescript generics type-inference typescript-generics


【解决方案1】:

棘手但似乎有效

//A constraint on this generic
type MyConstraint = { bar: number }
type GenericOne<T extends MyConstraint = MyConstraint> = {
    foo: T
}

【讨论】:

  • 你能解释一下为什么它可以提供默认值吗?如果泛型函数接受扩展 GenericOne 的类型参数,那不会删除一些类型信息吗?
  • 据我了解,您在这里有 2 个问题。 1.您不想在GenericOne中重复扩展类型,解决方案是默认类型。 2. 如果你要传递一个类型,你不想从 MyConstraint 扩展,我认为无论如何我们都可以避免这个限制,我不知道怎么做。那不会删除一些类型信息吗?可能不会,因为 T 仍然扩展 MyConstraint
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-11
  • 2019-06-27
  • 2021-07-04
  • 2019-12-18
  • 2018-12-22
  • 2017-01-21
相关资源
最近更新 更多