最终方案
https://docs.qq.com/aio/DUU5tSnJsY0NmZW1T
ts
// 类型定义 --------------------------------------------------------
// 深度只读包装
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends (...args: any[]) => any
? (...args: Parameters<T[K]>) => ReturnType<T[K]>
: T[K] extends object
? DeepReadonly<T[K]>
: T[K];
};
type Methods<T> = {
[K in keyof T as T[K] extends (...args: any[]) => any ? K : never]: T[K];
};
// 只返回方法
type MethodsOnly<T> = Pick<
T,
{
[K in keyof T]: T[K] extends (...args: any[]) => any ? K : never;
}[keyof T]
>;
type ServiceType<T, S> = DeepReadonly<Methods<T> & S>;
// Proxy处理器 ----------------------------------------------------
const createProxyHandler = (rawInstance: any) => ({
get(target: any, prop: string | symbol) {
// 优先返回selector属性
if (prop in target.__selector) {
return target.__selector[prop];
}
// 处理原型方法
const value = Reflect.get(target.__raw, prop);
if (typeof value === 'function') {
return (...args: any[]) => value.apply(rawInstance, args);
}
return value;
},
set() {
return false; // 完全禁止写操作
},
});
// 实现函数 --------------------------------------------------------
function useService<T extends new (...args: any[]) => any, S extends object>(
ClassName: T,
selector?: (instance: InstanceType<T>) => S
): ServiceType<InstanceType<T>, S> {
const rawInstance = new ClassName();
const selected = selector ? selector(rawInstance) : ({} as S);
// 创建代理对象
const proxy = new Proxy(
{
__raw: rawInstance, // 原始实例引用
__selector: selected, // selector结果
},
createProxyHandler(rawInstance)
);
return proxy as unknown as ServiceType<InstanceType<T>, S>;
}