跳至主要内容

多态分支

polymorphicBranch 步骤是一个实用程序步骤,用于处理通用的多态分支。

提示

在构建自己的步骤时,最好在您的步骤类上实现 planForType 方法,如 多态性 中所述。

polymorphicBranch 接受两个参数

  1. 表示要分支数据的步骤,
  2. 一个 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"),
},
});
},
},
},
});