多态分支
polymorphicBranch
步骤是一个实用程序步骤,用于处理通用的多态分支。
提示
在构建自己的步骤时,最好在您的步骤类上实现 planForType
方法,如 多态性 中所述。
polymorphicBranch
接受两个参数
- 表示要分支数据的步骤,
- 一个
matchers
对象,详细说明支持的类型以及如何匹配它们。
匹配器对象
// This type is for illustrative purposes only; the actual type is slightly
// more complex
type PolymorphicTypeMatchers = {
[typeName: string]: {
match?(obj: any): boolean;
plan?($obj: ExecutableStep): ExecutableStep;
};
};
匹配器对象是一个从支持的类型名称(字符串)到该类型的关联“匹配器”对象的映射。对于每个类型名称 typeName
,“匹配器”对象具有两个属性,这两个属性都是可选的
match(obj)
- 如果对象obj
是正在匹配的类型(typeName
),则返回true
;否则返回false
- 如果未设置,则默认为
(obj) => obj.__typename === typeName
- 如果未设置,则默认为
plan($obj)
- 假设步骤$obj
所代表的数据是正在匹配的类型,则返回一个表示此类型的步骤- 如果未设置,则默认为
($obj) => $obj
- 如果未设置,则默认为
示例
假设我们要表示一个动物数据库(我们使用数组来模拟)。由于不同类型的动物都有一个 name
,但具有不同的数据,我们将使用一个接口来表示 Animal
,然后我们将使用 polymorphicBranch
将对象缩小到正确的类型
import { makeGrafastSchema, polymorphicBranch, access, lambda } from "grafast";
// Our database of animals
const ANIMALS = [
{ type: "feline", name: "Artie", colour: "ginger" },
{ type: "feline", name: "Brontie", colour: "tortoise shell" },
{ type: "canine", name: "Captain", wagsTail: true },
{ type: "hamster", data: { name: "Hammy", type: "winter white dwarf" } },
];
const schema = makeGrafastSchema({
typeDefs: /* GraphQL */ `
interface Animal {
name: String!
}
type Cat implements Animal {
name: String!
colour: String!
}
type Dog implements Animal {
name: String!
wagsTail: Boolean!
}
type Hamster implements Animal {
name: String!
type: String!
}
type Query {
animal(id: Int!): Animal
}
`,
plans: {
Query: {
animal(_, { $id }) {
const $animal = lambda($id, (id) => ANIMALS[id - 1]);
return polymorphicBranch($animal, {
Cat: {
match: (obj) => obj.type === "feline",
},
Dog: {
match: (obj) => obj.type === "canine",
},
Hamster: {
match: (obj) => obj.type === "hamster",
// Notice the shape of `Hamster` is different, so we need to
// transform the object to represent a hamster. For other types
// this might even involve fetching details from a remote data
// source.
plan: ($obj) => access($obj, "data"),
},
});
},
},
},
});