通过复制粘贴学习graphql-scalars教程

首先

graphql-scalars是一個JavaScript庫,收集了GraphQL的自定義標量。它不僅可以嵌入應用程序中使用,還可以幫助了解自定義標量的具體例子,如EmailAddress類型和URL類型等,並且對於感興趣的人來說,如果查看源代碼,它可以作為自定義標量序列化/反序列化方法的參考實現的良好範例。

那么让我们在本教程中学习一下如何使用 graphql-scalars。

请提供参考文献。

    • GraphQL Scalars (graphql-scalars npm package) – Introduction

 

    • GraphQL (graphql.org) – Learn / Schemas and Types / Scalar types

 

    • Apollo Server – Custom scalars

 

    • Wantedly Engineer Blog – graphql-codegen と Nominal Typing(Branded Type) で Custom Scalar をちょっといい感じにする

 

    Richard Imaoka Notion – GraphQL custom scalar を使うモチベーションと graphql-scalars ライブラリ

事前准备 (Shì

请确认已安装Node.js和npm。

克隆 Git 代码库

请在终端中执行以下命令。

git clone https://github.com/richardimaoka/tutorial-graphql-scalars.git
cd tutorial-graphql-scalars

1. 设置 Apollo Server 和 GraphQL Codegen

让我们按照下图的方式使用3个终端。首先,在第一个终端上启动,然后从模版设置到执行GraphQL Codegen的步骤。

アートボード 15.png

请执行以下命令。可以直接全部复制并粘贴进行操作。

mkdir server
cd server

# node.js setup
npm init -y
echo "node_modules" > .gitignore

# install and initialize typescript
npm install --save-dev typescript
npx tsc --init

# ts-node-dev: watch and restart a TypeScript server
npm install --save-dev ts-node-dev
npm pkg set scripts.start="ts-node-dev --watch src/* --respawn src/index.ts"

# apollo server
npm install apollo-server graphql

# install and setup graphql-codegen
npm install --save-dev @graphql-codegen/cli
# ここで npx graphql-code-generator init を行ってもよいが、そうすると対話モードに入って手入力が増えるのと、
# 結局は npx graphql-code-generator init で生成されたconfig.ymlを上書き更新することになるので、以下はnpm installのみ行って config.ymlは後ほど作成
npm install --save-dev  @graphql-codegen/typescript @graphql-codegen/typescript-resolvers
npm pkg set scripts.generate="graphql-codegen --config codegen.yml --watch ./schema.gql" # update generate script

# copy files
mkdir src
mkdir data
curl https://raw.githubusercontent.com/richardimaoka/tutorial-apollo-server-setup/main/server/codegen.yml > codegen.yml
curl https://raw.githubusercontent.com/richardimaoka/tutorial-apollo-server-setup/main/server/schema.gql > schema.gql
curl https://raw.githubusercontent.com/richardimaoka/tutorial-apollo-server-setup/main/server/src/index.ts > src/index.ts
curl https://raw.githubusercontent.com/richardimaoka/tutorial-apollo-server-setup/main/server/data/Query.json > data/Query.json

请执行以下命令。

npm run generate

结果:如果以以下方式显示,那就没问题。

✔ Parse Configuration
✔ Generate outputs
  ℹ Watching for changes...

请保持这个终端不间断地运行 GraphQL Codegen 进程。

请打开一个新的终端。

アートボード 16.png

请执行以下命令。

cd server
npm start

结果:如果显示如下内容则表示OK。这样Apollo Server就启动成功了。

[INFO] 14:30:40 ts-node-dev ver. 1.1.8 (using ts-node ver. 9.1.1, typescript ver. 4.5.4)
?  Server ready at http://localhost:4000/

用 graphql-scalars 在 field 类型中进行操作验证

请打开一个新的终端。

アートボード 17.png

动作:请输入以下命令。

shellcheck disable=SC2164 # REMOVE THIS IN aggregate.sh
(cd server && npm install graphql-scalars)

请执行以下命令。

git apply patches/e7c78aa.patch # update schema.gql
结果:通过以上命令更新的 schema.gqlserver/schema.gql
标量 EmailAddress

类型 Person {
emailAddress: EmailAddress
name: String
}

类型 Query {
me: Person
}

结果:在这种状态下会出现错误终端
错误:在解析器中定义了Query.hello,但在模式中未定义

我们来解决这个错误吧。

请输入以下命令。

git apply patches/94f9796.patch # update index.ts
git apply patches/789bf5a.patch # update Query.json
结果:上述命令将更新index.ts文件。server/src/index.ts文件:

import { ApolloServer, gql } from “apollo-server”;
import * as fs from “fs”;
import { EmailAddressResolver } from “graphql-scalars”;
import { Query, Resolvers } from “./generated/graphql”;

const typeDefs = gql`
${fs.readFileSync(__dirname.concat(“/../schema.gql”), “utf8”)}
`;

interface LoadingDataContext {
Query: Query;
}

const resolvers: Resolvers = {
Query: {
me(_parent, _args, context, _info) {
return context.Query.me;
},
},
Person: {
name(parent, _args, _context, _info) {
return parent.name;
},
emailAddress(parent, _args, _context, _info) {
return parent.emailAddress;
},
},
EmailAddress: EmailAddressResolver,
};

const readJsonFile = async (relativeFileName: string): Promise => {
const jsonDataFile = __dirname.concat(relativeFileName);
const fileContent = await fs.promises.readFile(jsonDataFile, “utf8”);
const jsonData = JSON.parse(fileContent);
return jsonData;
};

const server = new ApolloServer({
typeDefs,
resolvers,
context: async ({ req }: any) => {
try {
const queryData: LoadingDataContext = await readJsonFile(
“/../data/Query.json”
);
return { Query: queryData };
} catch (err) {
console.log(“***发生错误***”);
console.log(err);
throw new Error(“发生内部错误!!”);
}
},
});

// `listen`方法启动一个Web服务器。
server.listen().then(({ url }) => {
console.log(`? 服务器已启动,URL为:${url}`);
});

结果:通过上述命令更新的 Query.json 是位于服务器/数据目录下的 Query.json 文件。
{
“me”: {
“emailAddress”: “jason.summerwinnter@gmail.com”,
“name”: “Jason Summerwinter”
}
}

请执行以下命令。

git apply patches/3e255ab.patch # return 10 in EmailAddress
结果:上述命令会更新 index.ts。在 server/src/index.ts 中:
邮箱地址(parent, _args, _context, _info){
– 返回 parent.emailAddress;
+ 返回 10;
}

2022-08-09_05h46_24.png

上述的源代码以 return 10 作为返回 number 类型的值,虽然运行时错误会被输出,但 TypeScript 的静态类型检查不会输出错误。

由于 number 类型无法表示 GraphQL 的 EmailAddress 类型的值,所以希望在 TypeScript 的类型检查中报错。因此,让我们进行以下更改。

请执行以下命令。

git apply patches/12e6f2b.patch # Update codegen.yml to set EmailAddress as string
结果: 使用上述命令更新的config.ymlconfig.yml
生成:
src/generated/graphql.ts:
插件:
– “typescript”
– “typescript-resolvers”
配置:
避免选项: true
+ 标量:
+ EmailAddress: 字符串

结果:随着config.yml的更改,generated/graphql.ts将会自动更新。server/src/generated/graphql.ts
export type Scalars = {
ID: string;
String: string;
Boolean: boolean;
Int: number;
Float: number;
– EmailAddress: any;
+ EmailAddress: string;
};

通過以上的更改,型检查会生效。在期望返回字符串的 emailAddress Resolver 中返回数字,会显示错误信息。

2022-08-06_21h33_37.png

尽管TypeScript的类型检查工作良好,但仅使用graphql-scalars提供的功能进行类型检查存在以下限制:

    • string が期待されるところで number を return するようなエラーを検出できます

 

    しかし、string ではあるものの、EmailAddress の形式として間違っているものはエラーにはなりません

让我们确认一下吧。

动作: 请输入以下命令。

git apply patches/0bfed3d.patch # wrong email address format passes type checking
结果:通过上述命令更新的index.tsserver/src/index.ts
emailAddress(parent, _args, _context, _info) {
– 返回10;
+ 返回”jason.summerwinter@@@@gmail.com”;
}

这里无法在 TypeScript 的类型检查中检测到错误,只能在运行时错误中检测到。

2022-08-08_00h28_44.png
要想在 TypeScript 的静态类型检查中,将不能转换为 EmailAddress 形式的 string 作为错误检测,需要使用此教程中介绍的第5和第6部分的技巧,使用自定义类型的定义。

既然我们已经了解了仅使用 graphql-scalars 提供的功能进行类型检查的操作,那么我们将把 emailAddress 恢复为从 Query.json 文件中获取值的形式。

请键入以下命令。

git apply patches/8dcf32c.patch # revert the emailAddress back to parent.emailAddress
结果:通过上述命令更新的index.ts是:server/src/index.ts
emailAddress(parent,_args,_context,_info){
– 返回“jason.summerwinnter@@@@gmail.com”;
+ 返回10;
}

在这里,让我们尝试使用除了EmailAddress之外的自定义标量。

请执行以下命令。

git apply patches/59c46fb.patch # many custom scalars
结果:上述命令将更新 Query.json。服务器/数据/Query.json
{
“me”: {
“name”: “Jason Summerwinter”,
“birthDate”: “1992-12-03T10:15:30Z”,
“ageInYears”: 30,
“heightInInches”: 180,
“minimumHourlyRate”: 3000,
“currentlyActiveProjects”: 3,
“emailAddress”: “jason.summerwinter@gmail.com”,
“homePage”: “https://json.summer.winter.com”,
“phoneNumber”: “+12312345678”,
“homePostalCode”: “010-0000”
}
}

结果:上述命令将更新 schema.gqlserver/schema.gql
+ 标量类型 DateTime
+ 标量类型 PositiveInt
+ 标量类型 PositiveFloat
+ 标量类型 NonNegativeFloat
+ 标量类型 NonNegativeInt
+ 标量类型 EmailAddress
+ 标量类型 URL
+ 标量类型 PhoneNumber
+ 标量类型 PostalCode

类型 Person {
– 邮箱地址: EmailAddress
姓名: String
+ 出生日期: DateTime
+ 年龄: PositiveInt
+ 身高: PositiveFloat
+ 最低小时费率: NonNegativeFloat
+ 当前进行项目数: NonNegativeInt
+ 电子邮箱地址: EmailAddress
+ 主页: URL
+ 电话号码: PhoneNumber
+ 家庭邮政编码: PostalCode
}

类型 Query {
我: Person
}

结果:上述命令会更新index.ts文件。server/src/index.ts
import { ApolloServer, gql } from “apollo-server”;
import * as fs from “fs”;
import { EmailAddressResolver } from “graphql-scalars”; // 导入EmailAddressResolver
import {
DateTimeResolver,
EmailAddressResolver,
NonNegativeFloatResolver,
NonNegativeIntResolver,
PhoneNumberResolver,
PositiveFloatResolver,
PositiveIntResolver,
PostalCodeResolver,
URLResolver,
} from “graphql-scalars”; // 导入其他解析器
import { Query, Resolvers } from “./generated/graphql”;

const typeDefs = gql`
// 类型定义部分略

const resolvers: Resolvers = {
// 解析器部分略
};

// 导出解析器部分略

2022-08-08_00h37_18.png

通过上述方式,我们已经知道如何使用多个自定义标量,因此让我们将源代码恢复为原始状态。

动作:请输入以下命令。

git apply patches/15071a8.patch # Revert "many custom scalars"

5. 对使用 graphql-scalars 作为参数类型的行为进行验证

迄今为止,我们已经讨论了如何在字段类型中使用自定义标量类型,现在让我们来看看参数类型的情况。我们将添加一个名为search的字段,并在该参数中使用自定义标量类型CountryCode。

请您输入以下命令。

git apply patches/b1acf0c.patch # add CountryCode to schema.gql
git apply patches/09bc748.patch # add country to index.ts
git apply patches/6c02fe8.patch # update data/Query.json
结果:上述命令会更新 schema.gql 文件server/schema.gql
标量 EmailAddress
+ 标量 CountryCode

类型 Person {
邮箱地址: EmailAddress
姓名: String
+ 国家: CountryCode
}

类型 Query {
我: Person
+ 搜索(国家: CountryCode): [Person]
}

结果:通过上述命令更新的index.ts文件server/src/index.ts
import { ApolloServer, gql } from “apollo-server”;
import * as fs from “fs”;
– import { EmailAddressResolver } from “graphql-scalars”;
+ import { CountryCodeResolver, EmailAddressResolver } from “graphql-scalars”;
import { Query, Resolvers } from “./generated/graphql”;

const typeDefs = gql`
@@ -16,6 +16,9 @@ const resolvers: Resolvers = {
me(_parent, _args, context, _info) {
return context.Query.me;
},
+ search(_parent, _args, context, _info) {
+ return context.Query.search;
+ },
},
Person: {
name(parent, _args, _context, _info) {
@@ -24,8 +27,12 @@ const resolvers: Resolvers = {
emailAddress(parent, _args, _context, _info) {
return parent.emailAddress;
},
+ country(parent, _args, _context, _info) {
+ return parent.country;
+ },
},
EmailAddress: EmailAddressResolver,
+ CountryCode: CountryCodeResolver,
};

const readJsonFile = async (relativeFileName: string): Promise => {

结果:通过上述命令更新的Query.json文件服务器/数据/Query.json
{
“me”: {
“emailAddress”: “jason.summerwinnter@gmail.com”,
– “name”: “Jason Summerwinter”
– }
+ “name”: “Jason Summerwinter”,
+ “country”: “JP”
+ },
+ “search”: [
+ {
+ “emailAddress”: “jason.fallspring@gmail.com”,
+ “name”: “Jason FallSpring”,
+ “country”: “JP”
+ },
+ {
+ “emailAddress”: “kate.heartspadediamond@gmail.com”,
+ “name”: “Kate HeartSpadeDiamond”,
+ “country”: “JP”
+ },
+ {
+ “emailAddress”: “yosuke.kishidamax@gmail.com”,
+ “name”: “Yosuke KishidaMax”,
+ “country”: “JP”
+ },
+ {
+ “emailAddress”: “bob.BobbDobb@gmail.com”,
+ “name”: “Bob BobbDobb”,
+ “country”: “JP”
+ }
+ ]
}

行动:请通过Apollo Studio Explorer执行查询并确认操作。

2022-08-09_06h00_03.png
image.png
2022-08-09_06h07_46.png

在 Apollo Studio Explorer 的查询编辑器中,静态类型检查错误不起作用。我们可以通过使用 argument 中的自定义标量来确认这种行为。

(可选)使用TypeScript的静态类型检查来检测无法将字符串转换为EmailAddress的格式错误。

在本教程“验证使用 graphql-scalars 作为字段类型时的操作”的最后,我们以以下方式进行了记录。

要使用TypeScript的静态类型检查来检测不能转换为EmailAddress的字符串格式错误,需要使用本教程中介绍的第5点和第6点的自定义类型定义技巧。

从这里开始,我们将实际观察这项技术。值得注意的是,在创建以下步骤时,我参考了 Wantedly Engineer Blog – graphql-codegen 和 Nominal Typing(Branded Type) 来将自定义标量优化得更好一些。

请执行以下指令。

git apply patches/2aa8329.patch # EmailAddressString type
结果: 上面的命令会生成src/myTypes.ts文件,其中str被定义为EmailAddressString,这是TypeScript的类型判断。src/myTypes.ts
导出类型EmailAddressString = 字符串 & { __type: “EmailAddressString” };

导出函数isEmailAddressString = (
str: 字符串
): str is EmailAddressString => {
const EMAIL_ADDRESS_REGEX =
/^[a-zA-Z0-9.!#$%&’*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;

返回 EMAIL_ADDRESS_REGEX.test(str);
};

那么,让我们在graphql.ts文件中进行设置,以导入已定义的EmailAddressString类型。由于graphql.ts是由GraphQL Codegen自动生成的,所以需要稍作修改。

请执行以下命令。

npm install --save-dev @graphql-codegen/add
git apply patches/e6f57b6.patch # Use EmailAddressString in codegen.yml
结果:通过以上命令更新的config.ymlconfig.yml
插件:
– “typescript”
– “typescript-resolvers”
+ – “add”:
+ 内容: “import * as myTypes from ‘../myTypes'”
配置:
避免选项: true
标量:
– 邮箱地址: string
+ 邮箱地址: myTypes.EmailAddressString
钩子:
在一个文件写入后:
– npx prettier –write

结果:根据config.yml自动更新的graphql.tsserver/src/generated/graphql.ts
+import * as myTypes from “../myTypes”;
export type Maybe = T | null;
export type InputMaybe = Maybe;
export type Exact = {
@@ -25,7 +26,7 @@ export type Scalars = {
Int: number;
Float: number;
CountryCode: any;
– EmailAddress: string;
+ EmailAddress: myTypes.EmailAddressString;
};

请执行以下命令。

git apply patches/fdf1ea5.patch # emailAddress does not allow plain string
结果:上述命令将更新index.ts文件server/src/index.ts
返回parent.name;
},
emailAddress(parent, _args, _context, _info) {
返回”jason.summerwinnter@gmail.com”;
},
country(parent, _args, _context, _info) {
返回parent.country;

2022-08-09_06h26_31.png

那么让我们来解决类型检查错误吧。

git apply patches/8b4740d.patch # explicit type checking by type predicates
结果:在上述命令中更新的index.ts文件
通过以下更改,明确调用isEmailAddress函数来检查字符串不仅仅是普通字符串,而是EmailAddressString。server/src/index.ts
emailAddress(parent, _args, _context, _info) {
– return “jason.summerwinnter@gmail.com”;
+ const email = “jason.summerwinnter@gmail.com”;
+ if (isEmailAddressString(email)) {
+ return email;
+ } else {
+ throw new Error(
+ “发生了内部错误:无法检索电子邮件地址”
+ );
+ }
},

由于使用了throw new Error,可能会认为最终只会导致运行时错误,但重点在于必须强制调用「isEmailAddressString」,程序员需要事先考虑在源代码的哪个部分进行类型检查,并明确地进行书写。

通过这样做,我现在可以利用TypeScript的类型检查来验证电子邮件地址的格式了!

在这种情况下,您可以通过调用“isEmailAddressString函数”来通过静态类型检查。换句话说,您不会在将意外值传递给GraphQL自定义标量的验证器后才意识到错误,而是在调用isEmailAddressString函数之前提前判断。

让我们假设在从数据库中调用的部分附近调用isEmailAddressString函数,并更新代码。

动作:请输入以下命令。

git apply patches/d065fdd.patch # email is validated near the database
结果:通过上述命令更新的index.tsserver/src/index.ts
const loadEmailDeepInsideServer = (): EmailAddressString => {
// 在服务器端的某个地方,比如数据库深处…
const valueFromDatabase = “jason.summerwinnter@gmail.com”;
if (isEmailAddressString(valueFromDatabase)) {
return valueFromDatabase;
} else {
throw new TypeError(
`数据库中的值 = ${valueFromDatabase} 不是有效的电子邮件地址`
);
}
};

interface LoadingDataContext {
Query: Query;
}

const resolvers: Resolvers = {
name(parent, _args, _context, _info) {
return parent.name;
},
emailAddress(_parent, _args, _context, _info) {
try {
const email = loadEmailDeepInsideServer();
return email;
} catch (error) {
// 仅服务器日志使用,不向API调用者公开内部错误详细信息
console.log(error);
throw new Error(
“发生内部错误:无法检索电子邮件地址”
);
}
}
};

请执行以下命令。

git apply patches/80dda3e.patch # wrong format email address
结果:通过上述命令更新的 index.tsserver/src/index.ts
const loadEmailDeepInsideServer = (): EmailAddressString => {
// 在服务器内部的某处,比如数据库…
const valueFromDatabase = “jason.summerwinnter@@@@gmail.com”;
if (isEmailAddressString(valueFromDatabase)) {
return valueFromDatabase;
} else {

请在Apollo Studio Explorer中执行查询。

2022-08-09_06h48_09.png
git apply patches/749a10a.patch # correct email format
结果: 使用上述命令更新的 index.tsserver/src/index.ts
const loadEmailDeepInsideServer = (): EmailAddressString => {
// 在服务器内部深处,比如数据库…
– const valueFromDatabase = “jason.summerwinnter@@@@gmail.com”;
+ const valueFromDatabase = “jason.summerwinnter@gmail.com”;
if (isEmailAddressString(valueFromDatabase)) {
return valueFromDatabase;
} else {

最后,让我们根据之前在5.中所做的更改恢复到最初状态。

行动:请输入以下命令。

git apply patches/6d06b65.patch # revert back index.ts

6.(可选)在 TypeScript 中为 GraphQL 的参数使用自定义类型

让我们为GraphQL的参数类型定义一个自定义的TypeScript类型,之前我们已经为GraphQL的字段类型定义了一个自定义的TypeScript类型。

git apply patches/e1814cb.patch # CoutryString type
结果:上述命令将更新myTypes.tsserver/src/myTypes.ts
+导出类型 CountryString = string & { __type: “CountryString” };
+
+导出函数 isCountryString = (str: string): str is CountryString => {
+ const COUNTRY_CODE_REGEX =
+ /^(AD|AE|AF|AG|AI|AL|AM|AO|AQ|AR|AS|AT|AU|AW|AX|AZ|BA|BB|BD|BE|BF|BG|BH|BI|BJ|BL|BM|BN|BO|BQ|BR|BS|BT|BV|BW|BY|BZ|CA|CC|CD|CF|CG|CH|CI|CK|CL|CM|CN|CO|CR|CU|CV|CW|CX|CY|CZ|DE|DJ|DK|DM|DO|DZ|EC|EE|EG|EH|ER|ES|ET|FI|FJ|FK|FM|FO|FR|GA|GB|GD|GE|GF|GG|GH|GI|GL|GM|GN|GP|GQ|GR|GS|GT|GU|GW|GY|HK|HM|HN|HR|HT|HU|ID|IE|IL|IM|IN|IO|IQ|IR|IS|IT|JE|JM|JO|JP|KE|KG|KH|KI|KM|KN|KP|KR|KW|KY|KZ|LA|LB|LC|LI|LK|LR|LS|LT|LU|LV|LY|MA|MC|MD|ME|MF|MG|MH|MK|ML|MM|MN|MO|MP|MQ|MR|MS|MT|MU|MV|MW|MX|MY|MZ|NA|NC|NE|NF|NG|NI|NL|NO|NP|NR|NU|NZ|OM|PA|PE|PF|PG|PH|PK|PL|PM|PN|PR|PS|PT|PW|PY|QA|RE|RO|RS|RU|RW|SA|SB|SC|SD|SE|SG|SH|SI|SJ|SK|SL|SM|SN|SO|SR|SS|ST|SV|SX|SY|SZ|TC|TD|TF|TG|TH|TJ|TK|TL|TM|TN|TO|TR|TT|TV|TW|TZ|UA|UG|UM|US|UY|UZ|VA|VC|VE|VG|VI|VN|VU|WF|WS|YE|YT|ZA|ZM|ZW)$/i;
+
+ 返回 COUNTRY_CODE_REGEX.test(str);
+};

请执行以下命令。

git apply patches/10f274d.patch # use CountryString in generated code
结果:通过以上命令更新的 config.yml 中的内容server/codegen.yml
避免使用可选项: true
标量:
电子邮件地址: myTypes.EmailAddressString
+ 国家代码: myTypes.CountryString
钩子:
在每次文件写入后:
– npx prettier –write

结果:config.yml会自动生成graphql.tsserver/src/generated/graphql.ts
Boolean: boolean;
Int: number;
Float: number;
– CountryCode: any;
+ CountryCode: myTypes.CountryString;
EmailAddress: myTypes.EmailAddressString;
};

请执行以下命令。

git apply patches/d224c5e.patch # args.country is typed as CountryString
结果:在上述命令中更新的index.tsserver/src/index.ts
me(_parent,_args,context,_info){
返回context.Query.me;
},
– 搜索(_parent,_args,context,_info){
+ 搜索(_parent,args,context,_info){
+ const countryString = args.country;
+ console.log(countryString);
返回context.Query.search;
},
},

2022-08-10_04h35_54.png

那么,让我们假设在服务器端逻辑的深层中会使用这个 CountryString 类型,让我们尝试重新编写代码。

请执行以下命令。

git apply patches/06d0d6c.patch # process args.country inside search
结果:上述命令将更新index.ts文件。server/src/index.ts

import { CountryString } from “./myTypes”;

const typeDefs = gql`
${fs.readFileSync(__dirname.concat(“/../schema.gql”), “utf8”)}
`;

// 处理 ‘country’ 变量,确保它是有效的国家代码
const deepInsideServer处理国家 = (country: CountryString) => {
console.log(country);
};

interface LoadingDataContext {
Query: Query;
}

const resolvers: Resolvers = {
// 省略其他代码
search(_parent, args, context, _info) {
const countryString = args.country;
deepInsideServer处理国家(countryString);
return context.Query.search;
},
},
“`

广告
将在 10 秒后关闭
bannerAds