【问题标题】:Typescript Mapped Types or Arrays of TypesTypescript 映射类型或类型数组
【发布时间】:2018-02-05 12:53:32
【问题描述】:

我正在尝试将 Typescript 映射类型用于简单的查询 API。让我提供一个简化的例子:

interface IRoot {
  user: IUser,
  trips: Array<ITrip>
}

interface IUser {
  name: string
}

interface ITrip {
  prop: string
}

现在我可以构造一个这样的查询:

class Query<T, K extends keyof T> {
  constructor(
    private rootType: T, 
    private subQueries?: {[P in K]?: Query<T[P], any> }) { }
}

这可以很好地访问用户,但无法解析旅行数组的类型:

new Query(({} as IRoot), {
  user: new Query(({} as IUser), ... /* This is a query on User and is accepted here */, 
  trips: new Query(({} as ITrip), ... /* This is a query on Trip and TS will complain, since T[P] is Array<ITrip> */
})

任何想法如何扩展{[P in K]?: Query&lt;T[P], any&gt; } 以接受T[P] 或者如果T[P] 是一个数组,数组的类型?

【问题讨论】:

  • trips: new Query(({} as Array&lt;ITrip&gt;), ... 不是你想要的吗?
  • 不,这会使 K 成为数组的属性,而不是 ITrip。相反,我想访问通过一对多关系链接的实体的道具。
  • 不认为有办法做到这一点,但也许你可以创建一个interface IQuery&lt;T&gt;,然后你可以有两个类Query&lt;T, K extends keyof T&gt;implements IQuery&lt;T&gt;)和ArrayQuery&lt;T, K extends keyof T&gt;(实现IQuery&lt;T[]&gt;)
  • 你能把IRoot中的trips定义为trips: Array&lt;ITrip&gt; | ITrip吗?
  • @Arg0n 不幸的是不是,因为查询结果在某些时候也使用 T[P] 并且查询返回一个查询引用数组。

标签: typescript


【解决方案1】:

一个想法是创建一个IQuery 接口并创建两个实现,一个用于简单属性,一个用于数组属性。 Query 将实现 IQuery,ArrayQuery 将实现 IQuery。 IQuery 接口需要有一个使用 T 的方法或字段,以确保 ArrayQuery&lt;T&gt;Query&lt;T&gt; 在结构上不兼容。

interface IQuery<T> {
    // We need this method since the compiler checks structural compatibility we need to make implementations of IQuery<T> and IQuery<T[]> incompatible.
    getRootType(): T;
}
class Query<T, K extends keyof T> implements IQuery<T>{
    constructor(
      private rootType: T, 
      private subQueries?: {[P in K]?: IQuery<T[P]> }) { 

      }
    getRootType(): T {
          return this.rootType;
    }
}

class ArrayQuery<T, K extends keyof T> implements IQuery<T[]>{
    constructor(private rootType: T,private  subQueries?: {[P in K]?: Query<T[P], any> }) { 

    }
    getRootType(): T[]{
        return [this.rootType];
    }
}

new Query(({} as IRoot), {
    user: new Query(({} as IUser)), 
    trips: new ArrayQuery(({} as ITrip)) 
});

【讨论】:

    猜你喜欢
    • 2018-03-02
    • 1970-01-01
    • 2017-08-08
    • 2019-03-21
    • 2018-06-25
    • 2023-04-04
    • 1970-01-01
    • 2018-10-19
    • 1970-01-01
    相关资源
    最近更新 更多