TypeScript patterns
All public types are re-exported from quadscan. No dist/types/...
hopping required.
Narrowing ScanResult.success
ScanResult.success is a discriminant. TypeScript narrows the rest of the
result when you check it:
import { Quadscan } from 'quadscan';
const r = await Quadscan.scan(file, { mode: 'extract' });
if (r.success) {
// r.corners is `CornerPoints` (non-null)
// r.output is the warped image, never null
r.corners.topLeft.x; // ok
r.output; // HTMLCanvasElement | ImageData | string
} else {
// r.message is the failure reason
console.warn(r.message);
}
If you want a stricter signal, the canonical pattern is to write a guard:
import type { ScanResult } from 'quadscan';
interface SuccessResult extends ScanResult {
success: true;
corners: NonNullable<ScanResult['corners']>;
confidence: number;
}
function isSuccess(r: ScanResult): r is SuccessResult {
return r.success && r.corners !== null;
}
Re-exporting library types
If your app passes corners across module boundaries, alias the types in a shared module:
// types/scan.ts
export type {
CornerPoint,
CornerPoints,
CornerPointsInput,
ScanResult,
ScanOptions,
} from 'quadscan';
Then import type { CornerPoints } from '@/types/scan' everywhere. Easier
to refactor later (e.g. wrap with your own shape).
using declarations
Quadscan implements Symbol.dispose. With TypeScript 5.2+ and a target of
ES2022 or later you can scope an instance:
{
using q = new Quadscan({ model: 'fastvit' });
await q.initialize();
for (const img of images) {
const r = await q.scan(img, { mode: 'extract' });
// ...
}
} // q.dispose() called automatically here
Particularly handy in routes / page-level handlers where you want a fresh session per page view.
Strict input types
ScanInput is the union of accepted shapes:
import type { ScanInput } from 'quadscan';
function preprocess(input: ScanInput) {
// ...
}
If you receive untyped data (e.g. from an event), narrow before calling
scan:
const data: unknown = getFromSomewhere();
if (
data instanceof Blob ||
data instanceof File ||
data instanceof HTMLImageElement ||
data instanceof HTMLCanvasElement
) {
await Quadscan.scan(data);
}
Quadscan.scan throws InvalidInputError on a bad shape. Narrowing
upstream is just nicer DX.