DrillLab
练习Practice

动手做Get your hands on it

练习跟着课文走 —— 每节课尾都有本课的练习。这一页是全部练习的总库,想集中刷题的时候来。 每个练习都写清了它来自哪一节,卡住了就回去看那一节。Practice follows the lessons — every lesson ends with the exercises for that lesson. This page is the whole library, for when you want to drill in one sitting. Each exercise names the lesson it came from, so you can go back when you stall.

0 / 148个做对过you got right

练习Exercises

筛出 148 个练习 · 第 6 / 13 页。Showing 148 · page 6 / 13.
来自From 变式四 · 递归读取评论的评论Variation 4 · reading replies to replies with recursion · React 考试React exam
L3Debug LabDebug LabDebug Lab · 回复加进去了,界面不动Debug Lab · the reply went in and the screen never movedDrillLab 自出Written by DrillLab

给深层评论加回复,console.log 打出来的树里 新回复确实在,但界面没变化。控制台干净。

You add a reply to a deep comment. The tree printed by console.log really does contain the new reply, but the screen does not change. The console is clean.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
# 没有任何报错。 $ npx vitest run src/CommentTree.test.tsx ✕ addReply 挂到深层节点,且不改原树 TypeError: Cannot add property 0, object is not extensible (测试把原树深冻结了,实现试图直接修改它) ✕ 给三层的评论再回复,落在正确的位置 Unable to find an element with the text: 第四层 # 手动复现:点某条评论的 Reply、输入、发送 # console.log(comments) -> 新回复确实在树里 # 屏幕 -> 一点变化都没有# No error at all. $ npx vitest run src/CommentTree.test.tsx ✕ addReply 挂到深层节点,且不改原树 TypeError: Cannot add property 0, object is not extensible (The test deep-froze the original tree; the implementation edits it in place.) ✕ 给三层的评论再回复,落在正确的位置 Unable to find an element with the text: 第四层 # Manual repro: click Reply on a comment, type something, send it # console.log(comments) -> the new reply really is in the tree # the screen -> nothing changes at all
TSXsrc/components/CommentTree/index.tsx示意Illustrative
1function addReply(nodes: Comment[], parentId: number, reply: Comment) {
2 for (const node of nodes) {
3 if (node.id === parentId) {
4 node.replies.push(reply); // 找到就塞进去
5 return nodes;
6 }
7 addReply(node.replies, parentId, reply);
8 }
9 return nodes;
10}
11
12const handleReply = (parentId: number, text: string) => {
13 const reply = { id: Date.now(), author: "我", body: text, replies: [] };
14 setComments(addReply(comments, parentId, reply));
15};
1function addReply(nodes: Comment[], parentId: number, reply: Comment) {
2 for (const node of nodes) {
3 if (node.id === parentId) {
4 node.replies.push(reply); // found it, so push it in
5 return nodes;
6 }
7 addReply(node.replies, parentId, reply);
8 }
9 return nodes;
10}
11
12const handleReply = (parentId: number, text: string) => {
13 const reply = { id: Date.now(), author: "我", body: text, replies: [] };
14 setComments(addReply(comments, parentId, reply));
15};
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this
来自From 变式五 · 主题切换:Context 怎么用Variation 5 · theme switching: how to use Context · React 考试React exam
L2填空Fill the blanks补全 ThemeContext 的四个关键位置Fill in the four key spots of ThemeContextDrillLab 自出Written by DrillLab

四个空。第 3 个是最容易漏的那一步,第 4 个决定「忘了套 Provider」 时报错清不清楚。

Four blanks. The third is the step people miss most. The fourth decides how clear the error is when somebody forgets to wrap things in the Provider.

TSXsrc/context/ThemeContext.tsx4 个空4 blanks
1const ThemeContext = <ThemeContextValue | undefined>(undefined);
2
3export function ThemeProvider({ children }: { children: ReactNode }) {
4 const [theme, setTheme] = useState<Theme>("light");
5
6 const toggleTheme = useCallback(() => {
7 setTheme();
8 }, []);
9
10 const value = (() => ({ theme, toggleTheme }), [theme, toggleTheme]);
11
12 return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;
13}
14
15export function useTheme(): ThemeContextValue {
16 const ctx = useContext(ThemeContext);
17 if () throw new Error("useTheme 必须在 <ThemeProvider> 里面用");
18 return ctx;
19}
把 4 个空都填上才能检查(还差 4 个)Fill all 4 blanks to check (4 to go)
来自From 变式五 · 主题切换:Context 怎么用Variation 5 · theme switching: how to use Context · React 考试React exam
L3写整块Write a block自己写出 ThemeProvider 和 useThemeWrite ThemeProvider and useTheme yourselfDrillLab 自出Written by DrillLab

类型已给好。写出 context、Provider、自定义 hook 三部分。 检查器会查记忆化、函数式更新和守卫。

The types are given. Write all three parts: the context, the Provider, and the custom hook. The checker looks for the memoization, the updater form and the guard.

要求Requirements
  • theme 初始为 'light'theme starts as 'light'
  • toggleTheme 在 light / dark 之间翻转,必须用函数式更新toggleTheme flips between light and dark, using the updater form
  • context value 要记忆化,theme 不变时不产生新对象The context value has to be memoized, so no new object appears while theme is unchanged
  • toggleTheme 引用要稳定(theme 变了它也不变)The reference of toggleTheme has to be stable, unchanged even when theme changes
  • 没套 Provider 就用 useTheme() 时抛出一句能看懂的错误Calling useTheme() with no Provider above it throws a message a person can read
  • 不许把 theme 存到组件外的全局变量里Do not keep theme in a global variable outside the component
TSXsrc/context/ThemeContext.tsx
This check is textual: it looks for the right constructs, it does not run your code
提示Hints共 4 级,已看 0 级4 levels, 0 opened
先自己想两分钟。想不出来再点右上角 —— 提示是一级一级放的,不会一次给完。Think for two minutes first. Then use the button above — hints come one level at a time, never all at once.

看答案之前,先确认你已经自己动手写过一遍。看懂别人的答案和自己写出来,是两种能力。Before you open this, make sure you have written it yourself once. Following someone else's answer and producing your own are two different skills.

来自From 变式五 · 主题切换:Context 怎么用Variation 5 · theme switching: how to use Context · React 考试React exam
L2Debug LabDebug LabDebug Lab · Cannot destructure property 'theme'DrillLab 自出Written by DrillLab

按钮好好的,卡片一渲染就整页白屏。这是真实报错。

The button is fine, and the moment the card renders the whole page goes blank. This is the real error.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
$ npx vitest run src/Theme.test.tsx TypeError: Cannot destructure property 'theme' of '(0 , __vite_ssr_import_1__.useTheme)(...)' as it is undefined. at ThemedCard (src/components/ThemedCard/index.tsx:6:11) at ThemeApp ✕ 默认是 light,按钮说 Switch to Dark ✕ 点一下变 dark:按钮文字和卡片底色一起变 ✕ 再点一下切回 light ✕ 没套 Provider 就用 useTheme(),必须立刻报错 ✕ toggleTheme 是稳定引用:theme 变了它也不变 Tests 5 failed | 3 passed (8) # 浏览器里的报错略有不同,意思一样: # Cannot destructure property 'theme' of 'useTheme(...)' as it is undefined.$ npx vitest run src/Theme.test.tsx TypeError: Cannot destructure property 'theme' of '(0 , __vite_ssr_import_1__.useTheme)(...)' as it is undefined. at ThemedCard (src/components/ThemedCard/index.tsx:6:11) at ThemeApp ✕ 默认是 light,按钮说 Switch to Dark ✕ 点一下变 dark:按钮文字和卡片底色一起变 ✕ 再点一下切回 light ✕ 没套 Provider 就用 useTheme(),必须立刻报错 ✕ toggleTheme 是稳定引用:theme 变了它也不变 Tests 5 failed | 3 passed (8) # The browser wording is slightly different but means the same thing: # Cannot destructure property 'theme' of 'useTheme(...)' as it is undefined.
TSXsrc/components/ThemeApp/index.tsx示意Illustrative
1// ThemeContext.tsx
2const ThemeContext = createContext<ThemeContextValue>(undefined as never);
3
4export function useTheme() {
5 return useContext(ThemeContext); // 没有守卫
6}
7
8// ThemeApp/index.tsx
9const ThemeApp: React.FC = () => (
10 <>
11 <ThemeProvider>
12 <ThemeToggleButton />
13 </ThemeProvider>
14 <ThemedCard />
15 </>
16);
1// ThemeContext.tsx
2const ThemeContext = createContext<ThemeContextValue>(undefined as never);
3
4export function useTheme() {
5 return useContext(ThemeContext); // no guard
6}
7
8// ThemeApp/index.tsx
9const ThemeApp: React.FC = () => (
10 <>
11 <ThemeProvider>
12 <ThemeToggleButton />
13 </ThemeProvider>
14 <ThemedCard />
15 </>
16);
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this
来自From Debug Lab · React 十种典型故障Debug Lab · ten typical React failures · React 考试React exam
L2Debug LabDebug Lab故障 1 · 路径大小写Fault 1 · upper and lower case in a path

新建了组件之后启动开发服务器,Vite 直接报错,页面白屏。

You add a new component, start the dev server, and Vite reports an error right away. The page is blank.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
[plugin:vite:import-analysis] Failed to resolve import "./components/notemanager" from "src/App.tsx". Does the file exist? /Users/me/react-notes-app/src/App.tsx:1:24 1 | import NoteManager from "./components/notemanager"; | ^
TSXsrc/App.tsx示意Illustrative
1import NoteManager from "./components/notemanager";
2
3function App() {
4 return <NoteManager />;
5}
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this
来自From Debug Lab · React 十种典型故障Debug Lab · ten typical React failures · React 考试React exam
L2Debug LabDebug Lab故障 2 · props 名字对不上Fault 2 · the prop names do not match

重构时把父组件传的 prop 名改了,子组件忘了跟着改。 页面能显示,但点 Delete 直接崩。

During a refactor the prop name passed by the parent was changed, and the child component was not changed to match. The page still renders, but clicking Delete crashes it.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
Uncaught TypeError: onDelete is not a function at onClick (NoteItem/index.tsx:18:29) at HTMLUnknownElement.callCallback # 另外 TypeScript 那边也在报: src/components/NoteTable/index.tsx(20,7): error TS2322: Type '{ key: number; note: Note; onRemove: (id: number) => void; onEdit: ... }' is not assignable to type 'IntrinsicAttributes & NoteItemProps'. Property 'onDelete' is missing in type ... but required in type 'NoteItemProps'.Uncaught TypeError: onDelete is not a function at onClick (NoteItem/index.tsx:18:29) at HTMLUnknownElement.callCallback # TypeScript is reporting something too: src/components/NoteTable/index.tsx(20,7): error TS2322: Type '{ key: number; note: Note; onRemove: (id: number) => void; onEdit: ... }' is not assignable to type 'IntrinsicAttributes & NoteItemProps'. Property 'onDelete' is missing in type ... but required in type 'NoteItemProps'.
TSX两处不一致The two places that disagree示意Illustrative
1// NoteTable 里传下去的名字:
2<NoteItem
3 key={note.id}
4 note={note}
5 onRemove={onDelete} // ← 传的是 onRemove
6 onEdit={onEdit}
7/>
8
9// NoteItem 的 props 接口和解构:
10export interface NoteItemProps {
11 note: Note;
12 onDelete: (id: number) => void; // ← 期望的是 onDelete
13 onEdit: (note: Note) => void;
14}
15const NoteItem: React.FC<NoteItemProps> = ({ note, onDelete, onEdit }) => {
1// The name NoteTable passes down:
2<NoteItem
3 key={note.id}
4 note={note}
5 onRemove={onDelete} // ← it passes onRemove
6 onEdit={onEdit}
7/>
8
9// The props interface of NoteItem, and how it destructures them:
10export interface NoteItemProps {
11 note: Note;
12 onDelete: (id: number) => void; // ← it expects onDelete
13 onEdit: (note: Note) => void;
14}
15const NoteItem: React.FC<NoteItemProps> = ({ note, onDelete, onEdit }) => {
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this
来自From Debug Lab · React 十种典型故障Debug Lab · ten typical React failures · React 考试React exam
L2Debug LabDebug Lab故障 3 · 测试找不到元素Fault 3 · the test cannot find the element

代码看起来完全正确,手动点也没问题,但两个测试挂了。

The code looks entirely correct and clicking through it by hand works, but two tests fail.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
FAIL src/NoteManager.test.tsx > adds a note TestingLibraryElementError: Unable to find an element by: [data-testid="form-input"] Ignored nodes: comments, script, style <body> <div> <div class="layout-column ..." data-testid="note-manager"> <div class="card ..."> <form data-testid="note-form"> <section class="layout-row ..."> <label class="form-title-label">Title:</label> <input type="text" placeholder="Title" data-testid="title-input" ... /> ...
TSXsrc/components/NoteForm/index.tsx示意Illustrative
1<input
2 type="text"
3 placeholder="Title"
4 value={title}
5 onChange={(e) => setTitle(e.target.value)}
6 data-testid="title-input"
7 className="form-input"
8/>
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this
来自From Debug Lab · React 十种典型故障Debug Lab · ten typical React failures · React 考试React exam
L3Debug LabDebug Lab故障 4 · 编辑后列表毫无变化(综合题)Fault 4 · the list does not change after an edit (mixed question)

这一题不告诉你是哪一类。控制台干净,console.log 显示数据是对的。 自己分诊。

This one does not tell you which category it is. The console is clean, and console.log shows the data is correct. Sort it yourself.

第 1 步 · 先看现象和代码,别急着改Step 1 · read the symptom and the code before you touch anything
# 没有任何报错。 # 复现:添加 "A"、"B" 两条 → 点 B 的 Edit → 改成 "B2" → 点 Update # 期望:列表变成 A、B2 # 实际:列表还是 A、B # 在 handleSubmitNote 里插了日志: console.log("submitted:", submittedNote); // → submitted: { id: 1785737900978, title: 'B2', content: '...' } ← 数据是对的 console.log("after:", notes); // → after: [ {title:'A'...}, {title:'B2'...} ] ← 数组里也是对的! # 但屏幕上还是 B。 # 测试结果: # ✕ edits a note in place# No error at all. # Repro: add "A" and "B" → click Edit on B → change it to "B2" → click Update # Expected: the list becomes A, B2 # Actual: the list is still A, B # Logs added inside handleSubmitNote: console.log("submitted:", submittedNote); // → submitted: { id: 1785737900978, title: 'B2', content: '...' } ← the data is right console.log("after:", notes); // → after: [ {title:'A'...}, {title:'B2'...} ] ← the array is right too! # But the screen still shows B. # Test result: # ✕ edits a note in place
TSX有问题的 handleSubmitNoteThe handleSubmitNote with the problem示意Illustrative
1const handleSubmitNote = (submittedNote: Note) => {
2 if (noteToEdit) {
3 const i = notes.findIndex((n) => n.id === submittedNote.id);
4 notes[i] = submittedNote;
5 setNotes(notes);
6 setNoteToEdit(null);
7 } else {
8 setNotes((prev) => [...prev, submittedNote]);
9 }
10};
第 2 步 · 这是什么类型的错误Step 2 · what kind of error is this
来自From 从零重写:空文件夹到 4 个测试全过Write it again yourself: from an empty folder to 4 passing tests · React 考试React exam
L4从零重写Rebuild from scratch从零重建 Q1 · Notes ManagerRebuild Q1 · Notes Manager

空目录开始,建出一个 React + TypeScript + Vite 项目, 实现 Notes Manager 的增删改,让下面那四个测试全过。不要打开 react-notes-app 参考。

Starting from an empty directory, build a React + TypeScript + Vite project. Implement add, delete and edit in Notes Manager, and make all four tests below pass. Do not open react-notes-app to look.

需求(不给代码,自己实现)Requirements — no code given, implement it yourself
  • 页面上方是表单:Title 输入框、Content 文本域、一个提交按钮The form sits at the top of the page: a Title input, a Content textarea, and one submit button
  • 页面下方是表格:表头 Title / Content / Edit / Delete,每条笔记一行The table sits below: the header is Title / Content / Edit / Delete, with one row per note
  • 两个输入框都必须是受控的(value + onChange)Both inputs must be controlled (value + onChange)
  • 标题或内容为空(含只有空格)时,提交按钮 disabledWhen the title or the content is empty (including only spaces), the submit button is disabled
  • Task 1 Add:提交后新笔记出现在表格末尾,原有的都还在Task 1 Add: after submit the new note appears at the end of the table, and every existing note is still there
  • Task 2 Delete:点某行的 Delete,该行按 id 被移除(同名笔记只删对的那条)Task 2 Delete: clicking Delete on a row removes that row by id (with notes of the same name, only the right one goes)
  • Task 3 Edit:点某行的 Edit → 内容回填进表单、按钮文字变成 UpdateTask 3 Edit: clicking Edit on a row fills its content back into the form, and the button text becomes Update
  • Task 3 提交后:该笔记在原位置被更新(顺序不变),然后退出编辑模式(表单清空、按钮回到 Add)Task 3 after submit: the note is updated in place (the order does not change), and edit mode ends (the form clears, the button goes back to Add)
  • 必须带上这些 data-testid:note-manager / note-form / form-input / form-textarea / form-submit-button / notes-listThese data-testid values are required: note-manager / note-form / form-input / form-textarea / form-submit-button / notes-list
  • 行内按钮的文字必须正好是 Edit 和 DeleteThe text on the row buttons must be exactly Edit and Delete
  • Note 的类型是 { id: number; title: string; content: string }The type of Note is { id: number; title: string; content: string }
你需要自己建的文件Files you create yourself
文件清单File list
package.json自己写 scripts 与依赖(react / react-dom / vite / @vitejs/plugin-react / typescript / vitest / jsdom / @testing-library/*)You write the scripts and dependencies (react / react-dom / vite / @vitejs/plugin-react / typescript / vitest / jsdom / @testing-library/*)
index.html一个 <div id="root"> 加一行 module scriptOne <div id="root"> plus one module script line
tsconfig.jsonstrict、jsx: react-jsx、moduleResolution: bundlerstrict, jsx: react-jsx, moduleResolution: bundler
vite.config.tsReact 插件 + 内联 vitest 配置(environment: jsdom、globals、setupFiles)The React plugin plus an inline vitest config (environment: jsdom, globals, setupFiles)
vitest.setup.tsimport "@testing-library/jest-dom"
src/main.tsxcreateRoot().render(<App />)
src/App.tsx渲染顶层组件Renders the top-level component
src/types/Note.tsNote 类型The Note type
src/components/NoteManager/index.tsx★ 状态所有者:notes + noteToEdit + 三个 handler★ The state owner: notes + noteToEdit + three handlers
src/components/NoteForm/index.tsx★ 受控表单、编辑回填、Add/Update 切换、提交时 id 的取舍★ The controlled form, filling values back for an edit, switching Add and Update, and choosing the id on submit
src/components/NoteTable/index.tsx表格骨架 + map + notes-list 的 testidThe table skeleton, the map, and the notes-list data-testid
src/components/NoteItem/index.tsx单行 + Edit / Delete 按钮One row plus the Edit and Delete buttons
src/NoteManager.test.tsx把四个测试抄进来当判卷器(见下方参考答案区)Copy the four tests in and let them grade you (see the reference answer area below)
写完后在本机这样验证Verify it locally like this
npm install
装完依赖,node_modules 与 package-lock.json 出现The dependencies install, and node_modules and package-lock.json appear
npm run dev
打开提示的 localhost 地址,能看到表单和空表格Open the localhost address it prints, and you see the form and an empty table
npx vitest run
Test Files 1 passed (1) / Tests 4 passed (4)
npm run dev
手动验证三件事:① 加三条同名笔记,删中间那条,只消失一条 ② 编辑中间那条,它还在第二行 ③ 更新完按钮回到 Add、表单清空Check three things by hand: ① add three notes with the same name, delete the middle one, and only one disappears ② edit the middle one and it is still on the second row ③ after the update the button goes back to Add and the form clears
提示Hints共 4 级,已看 0 级4 levels, 0 opened
先自己想两分钟。想不出来再点右上角 —— 提示是一级一级放的,不会一次给完。Think for two minutes first. Then use the button above — hints come one level at a time, never all at once.

这一关的意义就在于「没有答案也能写出来」。请确认你已经在本机建好文件、跑过验证命令,再打开参考答案对照。The whole point of this level is writing it with no answer in front of you. Create the files on your machine and run the verification commands first, then come back and compare.

Tick this once you have written it locally and the verification commands give the expected output.
来自From 从零重写:空文件夹到 4 个测试全过Write it again yourself: from an empty folder to 4 passing tests · React 考试React exam
L4从零重写Rebuild from scratch从零重建 Q2 · 并发任务调度器Rebuild Q2 · the concurrent task runner

只给类型定义和三条要求。自己写出 runTasks, 并自己写一个验证台来证明它对。

You get only the type definitions and three requirements. Write runTasks yourself, and write your own check harness to show that it is right.

需求(不给代码,自己实现)Requirements — no code given, implement it yourself
  • runTasks(tasks, limit) 接收一个「函数数组」,每个函数被调用后返回 PromiserunTasks(tasks, limit) takes an array of functions, and each function returns a Promise when it is called
  • 同一时刻最多 limit 个任务在运行;某个结束后立刻启动下一个At most limit tasks run at the same time; as soon as one finishes, start the next
  • 任何任务失败都不能让 runTasks 抛错No failing task may make runTasks throw
  • 返回数组顺序必须与 tasks 一致The order of the returned array must match tasks
  • 成功写 { status: "fulfilled", value },失败写 { status: "rejected", reason }On success write { status: "fulfilled", value }; on failure write { status: "rejected", reason }
  • 自己写一个 demo:6 个任务(其中至少 1 个 reject)、limit = 2,打印实时并发数与最终结果Write your own demo: 6 tasks (at least 1 of which rejects), limit = 2, printing how many run at each moment and the final results
你需要自己建的文件Files you create yourself
文件清单File list
package.json装 tsx 和 typescript,加一条跑 demo 的 scriptInstall tsx and typescript, and add one script that runs the demo
tsconfig.jsonstrict: true 就够了strict: true is enough
q2/taskRunner.ts★ Task / SettledResult 类型 + runTasks 实现★ The Task / SettledResult types plus the runTasks implementation
q2/demo.ts★ 自己写验证台:一个 running 计数器 + 6 个任务 + 打印★ Write the check harness yourself: one running counter, 6 tasks, and the printing
写完后在本机这样验证Verify it locally like this
npm install
装好 tsx 和 typescripttsx and typescript are installed
npm run q2
输出里 running now 从不超过 2;最终 6 条结果顺序与输入一致;reject 的那条是 { status: 'rejected', reason: Error }running now never goes above 2 in the output; the final 6 results are in the same order as the input; the rejected one is { status: 'rejected', reason: Error }
npx tsc --noEmit
没有类型错误No type errors
提示Hints共 4 级,已看 0 级4 levels, 0 opened
先自己想两分钟。想不出来再点右上角 —— 提示是一级一级放的,不会一次给完。Think for two minutes first. Then use the button above — hints come one level at a time, never all at once.

这一关的意义就在于「没有答案也能写出来」。请确认你已经在本机建好文件、跑过验证命令,再打开参考答案对照。The whole point of this level is writing it with no answer in front of you. Create the files on your machine and run the verification commands first, then come back and compare.

Tick this once you have written it locally and the verification commands give the expected output.
来自From GraphQL 是什么:一份 schema 加一堆 resolverWhat GraphQL is: one schema plus a set of resolvers · Federation 考试Federation exam
L1认出来Spot it哪些字段是标量Which fields are scalars

看真实 schema 里的 type Order。 下面哪些字段的类型是标量(不能再往下展开)?(多选)

Look at type Order in the real schema. Which of these fields have a scalar type — one that cannot be expanded any further? (Select all that apply.)

GraphQL SDL源项目From source
1type Order {
2 id: ID!
3 userId: ID!
4 status: OrderStatus!
5 totalAmount: Float!
6 items: [OrderItem!]!
7 createdAt: String!
8 shippingInfo: ShippingInfo
9}
Source: graphql-federation-practice/node-subgraph/src/schema.graphql

这题是多选。More than one answer is correct.

先选一个选项Pick an option first
来自From GraphQL 是什么:一份 schema 加一堆 resolverWhat GraphQL is: one schema plus a set of resolvers · Federation 考试Federation exam
L1认出来Spot it这个操作该放哪Where does this operation belong

真实 schema 里 createOrder 放在type Mutation 下。如果把它挪到type Query 下会怎样?

In the real schema, createOrder sits under type Mutation. What happens if you move it under type Query?

先选一个选项Pick an option first