我正在尝试正确键入一个使用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
字段的对象?
或者,我尝试键入assemblePage
和itemToEdge
,要求该项目属于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]
编辑:这是演示的工作版本,感谢@Aleksey L的帮助!
答案 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:
泛型允许您在添加约束的同时保留更具体的类型