常见问题

TypeScript 类型推导:如何让 useDevices / useDevicesProps 等获得完整 DP 类型?

useDevices、useDevicesProps、useDevicesActions、useStructuredDevicesProps、useStructuredDevicesActions 等多设备 Hooks 默认返回泛型类型,无法推导各设备 key 对应的具体 DP。推荐在项目的 typings/sdm.d.ts 中通过 declare module 覆写返回类型,实现 按设备 key 精确绑定 Schema。

第一步:为每种设备定义独立 Schema

在 src/devices/schema.ts 中,按设备 PID(角色)分别导出 Schema:

src/devices/schema.ts
// src/devices/schema.ts

/** 主设备 Schema */
export const mainDeviceSchema = [ /* 主设备实际 DPs */ ] as const;

/** lamp1 设备 Schema (PID: xxx) */
export const lampSchema = [ /* 灯具实际 DPs */ ] as const;

第二步:在 typings/sdm.d.ts 中覆写多设备 Hooks 类型

以 useDevices 为例,覆写返回的 MultiDevicesData;useDevicesProps、useDevicesActions 等会基于同一设备映射类型获得推导:

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']>;
  };

  // 按项目实际设备 key 定义映射
  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;
}

覆写后,所有多设备 Hooks 调用侧无需改动即可获得完整 DP 推导,例如:

const devicesData = useDevices();
devicesData.lamp1?.dpSchema.switch_led;   // ✓

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

个别页面设备类型不同时:局部类型收窄

若某个页面中特定 key 绑定了不同 Schema 的设备,可在该页面局部定义类型并通过 as 收窄,不影响其他页面:

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;