用于转换键值对象中对象属性的Typescript generic

用于转换键值对象中对象属性的Typescript generic,typescript,sorting,mongoose,Typescript,Sorting,Mongoose,排序给我一个具有columnName和排序方向的对象,我想将其转换为键值对象进行mongoose排序 返回值不匹配我不知道我缺少什么 我有以下接口: export enum SortDirection { asc = 'asc', desc = 'desc', } export class Sort<T> { columnName: keyof T direction: SortDirection } interface CriteriaRequestDto<

排序给我一个具有columnName和排序方向的对象,我想将其转换为键值对象进行mongoose排序

返回值不匹配我不知道我缺少什么

我有以下接口:

export enum SortDirection {
  asc = 'asc',
  desc = 'desc',
}

export class Sort<T> {
  columnName: keyof T
  direction: SortDirection
}

interface CriteriaRequestDto<T> {
  sort: Sort<T>
}

type SortQuery<T> = {
  [key in keyof T]?: SortDirection
}

buildSortQuery<T>(
    criteria: CriteriaRequestDto<T>,
  ): SortQuery<T> {
    if (!criteria || !criteria.sort) {
      return {}
    }
    const { columnName, direction } = criteria.sort

    return { [columnName]: direction }
  }
导出枚举排序方向{
asc=‘asc’,
desc='desc',
}
导出类排序{
专栏名称:keyof T
方向:排序方向
}
接口标准requestedto{
排序:排序
}
类型SortQuery={
[key in keyof T]?:排序方向
}
buildSortQuery(
标准:CriteriaRequestDto,
):SortQuery{
如果(!criteria | |!criteria.sort){
返回{}
}
常量{columnName,direction}=criteria.sort
返回{[columnName]:方向}
}


问题在这里
返回{[columnName]:direction}

当您期望
记录时,此符号表示
{[prop:string]:SortDirection}

根据我的经验,TS不能很好地处理计算对象属性。99%将缩小为索引类型
{[prop:string]:unknown}

为了解决这个问题,我做了一个
record
函数,它将返回
record

我是怎么做到的?我刚刚在函数中添加了一个重载

这是100%好的解决方案吗? 不,因为定义多个重载是一种好的做法

我想说重载比类型转换(
as
operator)安全一点,但只安全一点

所以我只定义了
record
函数的返回类型

函数记录(键:K,值:V):{[prop in K]:V}
功能记录(键:K,值:V){
返回{[key]:值}
}
因为下一个符号不起作用:

函数记录(键:K,值:V):{[prop in K]:V}{
返回{[key]:值}//错误
}
这里有完整的示例:

接口猫{
年龄:人数;
品种:弦;
}
枚举排序方向{
asc=‘asc’,
desc='desc',
}
接口排序{
专栏名称:keyof T
方向:排序方向
}
接口标准requestedto{
排序:排序
}
类型键=字符串|数字|符号;
函数记录(键:K,值:V):{[K中的prop]:V}
功能记录(键:K,值:V){
返回{[key]:值}
}
类型SortQuery=Partial
函数生成器查询(
标准:CriteriaRequestDto,
):SortQuery{
如果(!criteria | |!criteria.sort){
返回{}
}
常量{columnName,direction}=criteria.sort
返回记录(列名称、方向)
}
const sortQuery:sortQuery={}
sortQuery.age=SortDirection.asc//OK
常量排序:排序={
列名称:“年龄”//OK
方向:SortDirection.asc,//确定
}
常量标准:CriteriaRequestDto={
排序:排序//确定
}
const query=buildSortQuery(条件)
查询年龄

更新
请看一看。您不应该使用
作为
操作符

问题在于这里
返回{[columnName]:direction}

当您期望
记录时,此符号表示
{[prop:string]:SortDirection}

根据我的经验,TS不能很好地处理计算对象属性。99%将缩小为索引类型
{[prop:string]:unknown}

为了解决这个问题,我做了一个
record
函数,它将返回
record

我是怎么做到的?我刚刚在函数中添加了一个重载

这是100%好的解决方案吗? 不,因为定义多个重载是一种好的做法

我想说重载比类型转换(
as
operator)安全一点,但只安全一点

所以我只定义了
record
函数的返回类型

函数记录(键:K,值:V):{[prop in K]:V}
功能记录(键:K,值:V){
返回{[key]:值}
}
因为下一个符号不起作用:

函数记录(键:K,值:V):{[prop in K]:V}{
返回{[key]:值}//错误
}
这里有完整的示例:

接口猫{
年龄:人数;
品种:弦;
}
枚举排序方向{
asc=‘asc’,
desc='desc',
}
接口排序{
专栏名称:keyof T
方向:排序方向
}
接口标准requestedto{
排序:排序
}
类型键=字符串|数字|符号;
函数记录(键:K,值:V):{[K中的prop]:V}
功能记录(键:K,值:V){
返回{[key]:值}
}
类型SortQuery=Partial
函数生成器查询(
标准:CriteriaRequestDto,
):SortQuery{
如果(!criteria | |!criteria.sort){
返回{}
}
常量{columnName,direction}=criteria.sort
返回记录(列名称、方向)
}
const sortQuery:sortQuery={}
sortQuery.age=SortDirection.asc//OK
常量排序:排序={
列名称:“年龄”//OK
方向:SortDirection.asc,//确定
}
常量标准:CriteriaRequestDto={
排序:排序//确定
}
const query=buildSortQuery(条件)
查询年龄

更新
请看一看。返回
{[columnName]:direction}
Typescript时,不应将
用作
运算符

脚本将类型解释为
{[x:string]:SortDirection;}
。此类型具有
字符串
索引签名,因此不可分配给
SortQuery
,它只允许
T
的键作为属性。Typescript基本上是假设如果您从动态
字符串
键创建对象,那么该对象必须允许任何
字符串
键。这种假设是错误的

传播 另一方面,如果通过对象扩展将动态特性添加到现有对象,则Typescript将保留原始对象的类型,并且基本上忽略额外的特性

这是一种“黑客”解决方案,但如果将排序添加到空对象,则不会出现任何错误

return {
  ...{},
  [columnName]: direction
}
Typescript将返回的对象解释为type
{}
,这很好
const query: SortQuery<T> = {};
query[columnName] = direction;
return query;
const query: SortQuery<T> = {};
  
return {
  ...query,
  [columnName]: direction
}
return {
  [columnName]: direction
} as SortQuery<T>