---
title: FAQ
---

# FAQ

## TypeScript type inference: how do useDevices / useDevicesProps etc. get full DP types?

By default, multi-device Hooks such as `useDevices`, `useDevicesProps`, `useDevicesActions`, `useStructuredDevicesProps`, and `useStructuredDevicesActions` return generic types, so you don't get per-device DP inference. It is recommended to override their return types in your project's `typings/sdm.d.ts` using `declare module`, binding each device key to its exact Schema.

### Step 1: Define a separate Schema per device

In `src/devices/schema.ts`, export a Schema for each device PID (role):

```typescript
// src/devices/schema.ts

/** Main device Schema */
export const mainDeviceSchema = [ /* actual DPs */ ] as const;

/** lamp1 Schema (PID: xxx) */
export const lampSchema = [ /* actual DPs */ ] as const;
```

### Step 2: Override multi-device Hook types in typings/sdm.d.ts

Override the `MultiDevicesData` return type for `useDevices`; `useDevicesProps`, `useDevicesActions`, and the rest will then infer from the same device map:

```typescript
// typings/sdm.d.ts
export type LampSchema = typeof import('@/devices/schema').lampSchema;
type LampDevice = import('@ray-js/panel-sdk').SmartDeviceModel<LampSchema>;

declare module '@ray-js/panel-sdk' {
  export type LampInstanceData = {
    devInfo: ReturnType<LampDevice['getDevInfo']>;
    dpSchema: ReturnType<LampDevice['getDpSchema']>;
    network: ReturnType<LampDevice['getNetwork']>;
    bluetooth: ReturnType<LampDevice['getBluetooth']>;
  };

  export type MultiDevicesData = {
    main?: SmartDeviceInstanceData;
    lamp1?: LampInstanceData;
    lamp2?: LampInstanceData;
  };
  export function useDevices(): MultiDevicesData;
  export function useDevices<V>(
    selector: (devicesData: MultiDevicesData) => V,
    equalityFn?: (a: V, b: V) => boolean
  ): V;
}
```

After this override, all multi-device Hooks gain full DP inference at call sites with no other changes, for example:

```tsx | pure
const devicesData = useDevices();
devicesData.lamp1?.dpSchema.switch_led;   // ✓

const props = useDevicesProps(p => p);
props.lamp1?.switch_led;                   // ✓
```

### Per-page type narrowing when a device key has a different Schema

If a specific page binds a particular key to a different device Schema, define a local type and narrow it with `as` — other pages are unaffected:

```tsx | pure
import type { SmartDeviceInstanceData, LampInstanceData } from '@ray-js/panel-sdk';
import type { OtherLampInstanceData } from './types';

type MyPageDevicesData = {
  main?: SmartDeviceInstanceData;
  lamp1?: LampInstanceData;
  lamp2?: OtherLampInstanceData;
};

const devicesData = useDevices() as MyPageDevicesData;
```
