Skip to content

compat.native props type omits ref, though the runtime supports it #509

Description

@samgilmore-zr

Summary

compat.native's published props type (StrictPropsOnlyCompat in compat.d.ts) does not include ref, so TypeScript rejects:

<compat.native as="div" ref={ref} style={styles.x}>
  {(nativeProps) => <Pressable {...nativeProps} />}
</compat.native>

At runtime, refs work: the strict components destructure ref from props (React 19 ref-as-prop), wrap it via useStrictDOMElement, and fold it into nativeProps.ref before invoking function children — so the caller's ref receives the same DOM-emulation surface as html.* elements provide.

Details

html.d.ts re-adds ref per element with the Omit<StrictReactDOMProps, 'ref'> & { ref?: React.Ref<HTMLDivElement> } pattern, but compat.d.ts's StrictPropsOnlyCompat never got the same treatment:

type StrictPropsOnlyCompat<T> = Omit<
  StrictProps,
  keyof ({ as?: ...; children: (nativeProps: T) => React.ReactNode })
> & {
  as?: 'div' | 'img' | 'input' | 'span' | 'textarea';
  children: (nativeProps: T) => React.ReactNode;
};

Use case

We rebuilt our cross-platform Pressable primitive on compat.native so a single RNPressable IS the styled node (fixing shrink-wrapped touch targets from nesting an unstyled Pressable inside a styled html.div). Forwarding the component's ref requires a cast today:

const CompatNative = compat.native as unknown as React.ComponentType<{ ref?: React.Ref<HTMLDivElement>; ... }>;

Proposal

Add ref to StrictPropsOnlyCompat, ideally typed per the as element like the html.* declarations.

Version: react-strict-dom 0.0.55, React 19, React Native 0.85.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions