【发布时间】: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 不允许这样做。
我如何“传播”泛型类型的约束以避免在使用泛型类型的任何地方重复它?
【问题讨论】:
-
makeGenericOne的功能到底是什么?我可能遗漏了一些东西,但问题并不太清楚 -
如果你在第一个函数中省略了
extends MyConstraint,你至少会得到一个有用的错误Type 'T' does not satisfy the constraint 'MyConstraint'.所以即使你在那里重复自己,如果它不匹配它就不会编译,所以这一切都保持类型安全,以防您重构并忘记在两个地方进行更改。因此,在实践中,这并不是一个真正的问题,即使在大型代码库中也是如此。
标签: typescript generics type-inference typescript-generics