流:要求多态类型具有属性

时间:2018-09-25 05:00:08

标签: javascript flowtype

我正在尝试正确键入一个使用Flow泛型(或多态)类型的函数将一组对象分页到graphql / Relay样式的“页面”对象中。

这是一个简化的示例:

type DBNode = {
  uid: string
}

type Student = DBNode & {
  username: string
}

const students = [{
  uid: '123',
  username: 'user-one',
}, {
  uid: '345',
  username: 'user-two',
}]

type Classroom = DBNode & {
  room: number
}

const classrooms = [{
  uid: '234',
  room: 666,
}, {
  uid: '456',
  room: 667,
}]

type Edge<T> = {
  cursor: string,
  node: T
}

const itemToEdge = <T>(item: T): Edge<T> => ({
  cursor: item.uid,
  node: item
})

type Page<T> = {
  pageInfo: {
    count: number,
  },
  edges: Array<Edge<T>>
}        

const assemblePage = <T>(items: Array<T>): Page<T> => ({
  pageInfo: {
    count: items.length,
  },
  edges: items.map(itemToEdge)
})

const studentPage = (): Page<Student> => {
  return assemblePage(students)
}

const classroomPage = (): Page<Classroom> => {
  return assemblePage(classrooms)
}

我收到的错误是:

cursor: item.uid,
                   ^ Cannot get `item.uid` because property `uid` is missing in `T` [1].
References:
34: const itemToEdge = <T>(item: T): Edge<T> => ({
                                 ^ [1]

是否要确保多态类型T始终是具有uid字段的对象?

或者,我尝试键入assemblePageitemToEdge,要求该项目属于DBNode类型,结果是:

38:   node: item            ^ Cannot return object literal because `DBNode` [1] is incompatible with `T` [2] in property `node`.
References:
35: const itemToEdge = <T>(item: DBNode): Edge<T> => ({
                                 ^ [1]
31:   node: T            ^ [2]

Demo

编辑:这是演示的工作版本,感谢@Aleksey L的帮助!

Working Demo

1 个答案:

答案 0 :(得分:0)

您可以为通用类型参数定义约束:

const itemToEdge = <T: DBNode>(item: T): Edge<T> => ({
  cursor: item.uid,
  node: item
})
const assemblePage = <T: DBNode>(items: Array<T>): Page<T> => ({
  ...
})

来自docs

  

泛型允许您在添加约束的同时保留更具体的类型