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):
src/devices/schema.ts
// 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:
typings/sdm.d.ts
// 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:
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:
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;