Skip to content

Commit 67290fe

Browse files
matej21claude
andcommitted
refactor: replace as any type assertions with specific types across packages
Eliminate 18 problematic or improvable type assertions: - Replace `as any` with `Record<string, unknown>`, specific interfaces, or type guards - Add `RawContemberFieldDef` interface for SchemaRegistry normalization - Use explicit generics on `analyzeChildren().getAll<T>()` instead of casting results - Make `BlockDefinition.render` ref parameter nullable instead of casting undefined - Return real collector proxy from `collectorProxy.getById()` instead of empty `as any` - Introduce `CachedRelationHandle`/`CachedFieldHandle` interfaces in EntityHandle - Use `as Partial<SlateElement>` for editor list transforms instead of `as any` Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent ad2c2be commit 67290fe

19 files changed

Lines changed: 133 additions & 105 deletions

File tree

packages/bindx-client/src/schema/SchemaRegistry.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,14 @@ export class SchemaRegistry<TModels extends Record<string, object> = Record<stri
248248
}
249249
}
250250

251+
/** Raw field format from Contember SchemaNames (column/one/many with entity). */
252+
interface RawContemberFieldDef {
253+
readonly type: string
254+
readonly entity?: string
255+
readonly target?: string
256+
readonly inverse?: string
257+
}
258+
251259
/**
252260
* Normalizes field definitions from Contember SchemaNames format
253261
* (column/one/many with entity) to bindx FieldDef format (scalar/hasOne/hasMany with target).
@@ -257,24 +265,23 @@ function normalizeEntityDef(entityDef: EntitySchemaDef): EntitySchemaDef {
257265
let needsNormalization = false
258266

259267
for (const [fieldName, fieldDef] of Object.entries(entityDef.fields)) {
260-
const raw = fieldDef as unknown as Record<string, unknown>
261-
const type = raw['type'] as string
268+
const raw = fieldDef as RawContemberFieldDef
262269

263-
if (type === 'column') {
270+
if (raw.type === 'column') {
264271
fields[fieldName] = { type: 'scalar' }
265272
needsNormalization = true
266-
} else if (type === 'one') {
273+
} else if (raw.type === 'one') {
267274
fields[fieldName] = {
268275
type: 'hasOne',
269-
target: (raw['entity'] as string) ?? (raw['target'] as string),
270-
inverse: raw['inverse'] as string | undefined,
276+
target: (raw.entity ?? raw.target)!,
277+
inverse: raw.inverse,
271278
}
272279
needsNormalization = true
273-
} else if (type === 'many') {
280+
} else if (raw.type === 'many') {
274281
fields[fieldName] = {
275282
type: 'hasMany',
276-
target: (raw['entity'] as string) ?? (raw['target'] as string),
277-
inverse: raw['inverse'] as string | undefined,
283+
target: (raw.entity ?? raw.target)!,
284+
inverse: raw.inverse,
278285
}
279286
needsNormalization = true
280287
} else {

packages/bindx-dataview/src/HasManyDataGrid.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ function HasManyDataGridImpl<TEntity extends object>({
206206

207207
const relationData = (result.data[alias] ?? result.data[fieldName]) as Array<Record<string, unknown>> | undefined
208208
const totalCount = Array.isArray(relationData) && 'totalCount' in relationData
209-
? (relationData as unknown as { totalCount: number }).totalCount
209+
? (relationData as Array<Record<string, unknown>> & { totalCount: number }).totalCount
210210
: undefined
211211

212212
if (!Array.isArray(relationData)) {

packages/bindx-dataview/src/columnTypes.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ export function defineColumnType<TValue, TFilterArtifact extends FilterArtifact>
5757
*/
5858
export function accessField(accessor: EntityAccessor<object>, fieldName: string): unknown {
5959
// EntityAccessor is a Proxy — bracket access goes through the get trap
60-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
61-
return (accessor as any)[fieldName]
60+
return (accessor as unknown as Record<string, unknown>)[fieldName]
6261
}
6362

6463
function extractScalarValue<T>(accessor: EntityAccessor<object>, fieldName: string): T | null {

packages/bindx-dataview/src/select/SelectDataView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ function SelectDataViewImpl({
8686

8787
const { selection, queryKey } = useMemo(() => {
8888
const scope = new SelectionScope()
89-
const collector = createCollectorProxy<object>(scope, entityType, schemaRegistry ?? undefined) as unknown as EntityAccessor<object>
89+
const collector = createCollectorProxy<object>(scope, entityType, schemaRegistry ?? undefined) as EntityAccessor<object>
9090

9191
if (selectionDefinerRef.current) {
9292
const jsx = selectionDefinerRef.current(collector)

packages/bindx-dataview/src/useDataGridSetup.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,15 @@ export function useDataGridSetup<TEntity extends object>({
102102
// ---- Phase 1: Collection ----
103103
const { childrenJsx, columns, selection, queryKey, toolbarContent, layoutRenders, layoutElements, effectiveLayouts } = useMemo(() => {
104104
const scope = new SelectionScope()
105-
const collector = createCollectorProxy<TEntity>(scope, entityType, schemaRegistry ?? undefined) as unknown as EntityAccessor<TEntity>
105+
// Collector proxy satisfies EntityAccessor interface at runtime for selection collection
106+
const collector = createCollectorProxy<TEntity>(scope, entityType, schemaRegistry ?? undefined) as EntityAccessor<TEntity>
106107

107108
const jsx = children(collector)
108109
const analysis = analyzeChildren(jsx, MARKER_TYPES)
109110

110-
const cols = analysis.getAll(ColumnLeaf) as unknown as ColumnLeafProps[]
111-
const toolbarMarker = analysis.getFirst(DataGridToolbarContent) as DataGridToolbarContentProps | undefined
112-
const layoutMarkers = analysis.getAll(DataGridLayout) as unknown as DataGridLayoutProps[]
111+
const cols = analysis.getAll<ColumnLeafProps>(ColumnLeaf)
112+
const toolbarMarker = analysis.getFirst<DataGridToolbarContentProps>(DataGridToolbarContent)
113+
const layoutMarkers = analysis.getAll<DataGridLayoutProps>(DataGridLayout)
113114

114115
for (const col of cols) {
115116
col.collectSelection?.(collector)
@@ -119,13 +120,13 @@ export function useDataGridSetup<TEntity extends object>({
119120
const elements = new Map<string, readonly DataViewElementData[]>()
120121
for (const marker of layoutMarkers) {
121122
const layoutCallback = marker.children as (item: EntityAccessor<object>) => ReactNode
122-
const layoutJsx = layoutCallback(collector as unknown as EntityAccessor<object>)
123+
const layoutJsx = layoutCallback(collector as EntityAccessor<object>)
123124
const layoutSel = collectSelection(layoutJsx)
124125
mergeSelections(scope.toSelectionMeta(), layoutSel)
125126
renders.set(marker.name, layoutCallback)
126127

127128
const elementAnalysis = analyzeChildren(layoutJsx, ELEMENT_MARKER_TYPES)
128-
const elementProps = elementAnalysis.getAll(DataViewElement) as unknown as DataViewElementProps[]
129+
const elementProps = elementAnalysis.getAll<DataViewElementProps>(DataViewElement)
129130
if (elementProps.length > 0) {
130131
elements.set(marker.name, elementProps.map(it => ({ name: it.name, label: it.label, fallback: it.fallback })))
131132
}

packages/bindx-editor/src/components/BlockEditor.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ function BlockElementRenderer<
225225
return <BlockElementWithRef block={block} renderProps={renderProps} />
226226
}
227227

228-
return <>{block.render({ ...renderProps, isVoid: block.isVoid }, undefined as unknown as EntityAccessor<TEntity, TSelected, TBrand, TEntityName, TSchema>)}</>
228+
return <>{block.render({ ...renderProps, isVoid: block.isVoid }, null)}</>
229229
}
230230

231231
function BlockElementWithRef<

packages/bindx-editor/src/editor/createEditorWithEssentials.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const createEditorWithEssentials = ({ defaultElementType }: { defaultElem
2222
slate: Slate,
2323
formatVersion: 1,
2424
defaultElementType,
25-
isDefaultElement: element => 'type' in element && (element as any).type === defaultElementType,
25+
isDefaultElement: element => 'type' in element && (element as Record<string, unknown>)['type'] === defaultElementType,
2626
createDefaultElement: children => ({
2727
type: defaultElementType,
2828
children,

packages/bindx-editor/src/internal/hooks/useBlockEditorReferences.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,10 @@ export function useBlockEditorReferences<
7171
const tempId = references.add()
7272
const entityAccessor = references.getById(tempId)
7373

74-
// Set discrimination field
75-
const fieldHandle = entityAccessor as unknown as { field: (name: string) => { setValue: (v: unknown) => void } }
76-
if ('field' in fieldHandle) {
77-
fieldHandle.field(discriminationField).setValue(name)
74+
// Set discrimination field via proxy (EntityAccessor proxy resolves string keys to field handles)
75+
const fieldRef = (entityAccessor as Record<string, unknown>)[discriminationField]
76+
if (fieldRef && typeof fieldRef === 'object' && 'setValue' in fieldRef) {
77+
(fieldRef as { setValue: (v: unknown) => void }).setValue(name)
7878
}
7979

8080
init?.(entityAccessor)

packages/bindx-editor/src/plugins/attributes/alignment/alignButton.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const createAlignHandler = (direction: AlignDirection): {
1515
return Array.from(Editor.nodes(editor, { match: it => isAlignTarget(editor, it, direction) })).length > 0
1616
},
1717
isActive: ({ editor }) => {
18-
return Array.from(Editor.nodes(editor, { match: it => isAlignTarget(editor, it, direction) && (it as any).align === direction })).length > 0
18+
return Array.from(Editor.nodes(editor, { match: it => isAlignTarget(editor, it, direction) && 'align' in it && (it as Record<string, unknown>)['align'] === direction })).length > 0
1919
},
2020
toggle: ({ editor }) => {
2121
Transforms.setNodes(editor, {

packages/bindx-editor/src/plugins/element/lists/transforms/dedentListItem.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export const dedentListItem = (
3535
const parentAndGrandParentAreCompatible = BindxEditor.isElementType(
3636
grandParentListElement,
3737
parentListElement.type,
38-
parentListElementSpecifics as any,
38+
parentListElementSpecifics as Partial<SlateElement>,
3939
)
4040

4141
// TODO we need to handle following siblings!!!

0 commit comments

Comments
 (0)