Skip to content

Commit e195092

Browse files
os-zhuangclaude
andauthored
test(verify): drop as never at every checkDateBucketParity/checkReadCoercion call site (#6354) (#6396)
`@objectstack/verify` declares `BucketableDriver` / `CoercibleDriver` as structural doubles for the driver under test. Every call site in the repo cast the driver to `never` first, so the one thing the doubles exist to express — "this driver really does have that set of methods" — was never checked anywhere. Removes all 10 casts (6 dogfood parity, 2 turso parity, 2 dogfood read-coercion). Zero runtime change, zero new escape hatches. Claude-Session: https://claude.ai/code/session_01WyvqvKMG6asi9aXjKE6xtx Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent 9766d4f commit e195092

4 files changed

Lines changed: 27 additions & 10 deletions

File tree

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
"@objectstack/driver-turso": patch
3+
---
4+
5+
test(verify): `checkDateBucketParity` / `checkReadCoercion` 的调用点不再 `as never`,替身的编译期检查恢复生效 (#6354)
6+
7+
`@objectstack/verify``BucketableDriver` / `CoercibleDriver` 两个**结构替身**表达「被测驱动确实具备这组方法」。这是一个**已发布**的契约面——仓外驱动(cloud 的 `driver-turso`)照着它实现自己的一致性测试。但全仓 **10 个**调用点无一例外把驱动 `as never` 之后再传进去,于是这件事**一次也没有被检查过**:替身存在的全部意义,被 100% 的调用点关掉了。
8+
9+
本次逐处删掉这 10 个 cast,一个不留:
10+
11+
- `packages/qa/dogfood/test/date-bucket-parity-conformance.test.ts` **6 处**(真实 `SqlDriver` / `SqliteWasmDriver` 1 处,负向控制的假驱动 5 处)
12+
- `packages/drivers/driver-turso/src/date-bucket-parity.test.ts` **2 处**`TursoDriver` 本地模式 + 那条 `week` 绊线)
13+
- `packages/qa/dogfood/test/read-coercion-conformance.test.ts` **2 处**`checkReadCoercion` 同族,同形且同样是死 cast)
14+
15+
**零运行时改动,零新增逃逸口**——只删不加,全程未引入任何 `as any` / `as unknown as` / `@ts-expect-error` / `as never`。三个包 typecheck 全绿:这些 cast 每一个都是死的,替身与真实驱动的形状本来就一致,被抹掉的只是**说出这件事**的能力。
16+
17+
代价原本是休眠的,也正因为休眠才值得修:哪天某个驱动少掉替身要求的一个方法、或替身自身长出新成员,10 个调用点一个都不会红,`checkDateBucketParity` 会在运行期抛 `driver.aggregate is not a function`,而不是在 `tsc` 里被拦下。对仓外驱动作者而言,这个替身是他们唯一能对照的形状说明书,而说明书此前从不校验。

packages/drivers/driver-turso/src/date-bucket-parity.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ describe('TursoDriver date-bucket parity (framework#3773)', () => {
4040
const driver = new TursoDriver({ url: ':memory:' });
4141
expect(driver.transportMode).toBe('local');
4242

43-
const problems = await checkDateBucketParity(driver as never, {
43+
const problems = await checkDateBucketParity(driver, {
4444
createOptions: { bypassTenantAudit: true },
4545
});
4646
expect(problems).toEqual([]);
@@ -125,7 +125,7 @@ describe('TursoDriver date-bucket parity (framework#3773)', () => {
125125
configurable: true,
126126
});
127127

128-
const problems = await checkDateBucketParity(driver as never, {
128+
const problems = await checkDateBucketParity(driver, {
129129
createOptions: { bypassTenantAudit: true },
130130
});
131131
expect(problems.join('\n')).toMatch(/advertises this granularity but aggregate\(\) threw/);

packages/qa/dogfood/test/date-bucket-parity-conformance.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const DRIVERS = [
4646

4747
describe.each(DRIVERS)('date-bucket parity conformance: $name', ({ make }) => {
4848
it('buckets identically pushed-down and in-memory, on both storage forms', async () => {
49-
const problems = await checkDateBucketParity(make() as never, {
49+
const problems = await checkDateBucketParity(make(), {
5050
createOptions: { bypassTenantAudit: true },
5151
});
5252
expect(problems).toEqual([]);
@@ -87,7 +87,7 @@ describe('checkDateBucketParity detects a driver whose SQL bucketing is wrong',
8787
}
8888

8989
it('flags every advertised granularity on both columns', async () => {
90-
const problems = await checkDateBucketParity(brokenDriver() as never);
90+
const problems = await checkDateBucketParity(brokenDriver());
9191
// 4 advertised granularities × 2 storage forms = 8 disagreements, and the
9292
// cross-column pass stays quiet because both columns are broken the same way.
9393
expect(problems).toHaveLength(8);
@@ -102,7 +102,7 @@ describe('checkDateBucketParity detects a driver whose SQL bucketing is wrong',
102102
async aggregate() {
103103
throw new Error("dateGranularity 'month' not supported on dialect");
104104
},
105-
}) as never,
105+
})
106106
);
107107
expect(problems.join('\n')).toMatch(/advertises this granularity but aggregate\(\) threw/);
108108
});
@@ -124,7 +124,7 @@ describe('checkDateBucketParity detects a driver whose SQL bucketing is wrong',
124124
return [{ at: null, n: 8 }];
125125
},
126126
supports: { queryDateGranularity: { year: true } },
127-
}) as never,
127+
})
128128
);
129129
expect(problems.join('\n')).toMatch(/Field\.datetime 'at' @ year/);
130130
expect(problems.join('\n')).toMatch(
@@ -153,15 +153,15 @@ describe('checkDateBucketParity detects a driver whose SQL bucketing is wrong',
153153
];
154154
},
155155
supports: { queryDateGranularity: { year: true } },
156-
}) as never,
156+
})
157157
);
158158
expect(problems.join('\n')).toMatch(/pushed-down SQL and in-memory bucketing disagree/);
159159
expect(problems.join('\n')).toContain(sentinel);
160160
});
161161

162162
it('stays quiet on a driver that advertises nothing', async () => {
163163
const problems = await checkDateBucketParity(
164-
brokenDriver({ supports: { queryDateGranularity: {} } }) as never,
164+
brokenDriver({ supports: { queryDateGranularity: {} } })
165165
);
166166
// Nothing advertised ⇒ the engine buckets everything in-memory ⇒ nothing to
167167
// disagree about. A driver is never faulted for declining.

packages/qa/dogfood/test/read-coercion-conformance.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const DRIVERS = [
3737

3838
describe.each(DRIVERS)('read-coercion conformance: $name', ({ make }) => {
3939
it('reads a stored row back as its declared types (boolean/json/number)', async () => {
40-
const problems = await checkReadCoercion(make() as never);
40+
const problems = await checkReadCoercion(make());
4141
expect(problems).toEqual([]);
4242
});
4343
});
@@ -53,7 +53,7 @@ describe('checkReadCoercion detects a non-coercing driver', () => {
5353
return [{ id: '1', name: 'Widget', active: 1, meta: '{"k":1,"arr":[1,2]}', count: '5' }];
5454
},
5555
};
56-
const problems = await checkReadCoercion(raw as never);
56+
const problems = await checkReadCoercion(raw);
5757
expect(problems).toHaveLength(3);
5858
expect(problems.join('\n')).toMatch(/boolean not coerced/);
5959
expect(problems.join('\n')).toMatch(/json not coerced/);

0 commit comments

Comments
 (0)