你遇到的问题是
type OrderByType<T> = { [K in keyof Partial<T>]: 'asc' | 'desc'; };
似乎对于编译器来说,对于generic、Entity
、constrained到{ createdAt: Date }
来说,{ createdAt: 'asc' }
可以赋给OrderByType<keyof Entity>
的嵌套层太多了.
这类问题被报告为microsoft/TypeScript#27598,尽管它被认为可以正常工作.一般来说,编译器并不擅长知道像{createdAt: 'asc'}
这样的具体类型何时可以赋值给像OrderByType<T>
这样的泛型类型,除非有人显式编写了编译器代码路径来处理它.
幸运的是,我们可以重构您的代码,使其正常工作:
The Partial
utility type只是使用mapping modifier将所有属性变为可选.因此,您的OrderByType<T>
实际上是{[K in keyof {[P in keyof T]?: T[P]}]: 'asc' | 'desc'}
,它放置一个内部映射类型来添加可选修饰符,然后放置一个外部映射类型来仅保留这些修饰符.
如果您将其更改为概念上相同但更简单的实现
type OrderByType<T> = { [K in keyof T]?: 'asc' | 'desc' }
然后事情就开始运转了:
export class OrderByArgs<Entity extends { createdAt: Date }> {
orderBy: OrderByType<Entity> = { createdAt: 'asc' }; // okay
现在对编译器来说很明显,OrderByType<T>
本身肯定是一个全可选的类型,而且由于createdAt
肯定是Entity
的键,那么无论Entity
中有多少额外的键,{createdAt: 'asc'}
都肯定可以赋值给OrderByType<Entity>
.
Playground link to code个