TypeScript中创建索引签名实现对子对象的代理访问问题
Hey there! No worries at all—we’ve all stumbled through TypeScript’s proxy and type intersection quirks when starting out. Let’s break down how to fix this issue cleanly.
The Core Problem
Your AType is an intersection of your class’s base functionality plus StateType, so TypeScript expects class A to actually implement all StateType properties directly. But since you’re using a proxy to forward those property accesses to state instead, TypeScript can’t automatically infer that the proxy will handle those missing properties.
Solution 1: Explicit Type Alignment with Proxy
We can split the types to separate what the class actually implements vs. what the proxy exposes, then explicitly tell TypeScript what the proxy returns. Here’s the adjusted code:
// Define the core state type type StateType = { someVal: number; }; // Define what the class A actually implements (no StateType properties here) type ABase = { state: StateType; doubleSomeVal(): number; }; // The public type we want to expose: core functionality + state properties type AType = ABase & StateType; class A implements ABase { state: StateType; doubleSomeVal() { return this.state.someVal * 2; } constructor(state: StateType) { this.state = state; } static create(state: StateType): AType { return new Proxy(new A(state), { get(target: A, key: keyof AType) { // Forward StateType property accesses to target.state if (key in target.state) { return (target.state as Record<string, unknown>)[key]; } // Fall back to the class's own properties/methods return (target as Record<string, unknown>)[key]; } }) as AType; // Assert the proxy matches our desired public type } }
Why This Works:
- We split
ATypeintoABase(what the class truly implements) and the intersection withStateType(what the proxy exposes). This avoids forcing the class to define properties it doesn’t actually have. - The
createmethod explicitly returnsAType, and we use a type assertion to tell TypeScript the proxy instance matches this type (since TS can’t infer proxy behavior on its own). - The proxy’s
gethandler checks if the key exists instatefirst, falling back to the class’s own members if not.
Solution 2: Getters (For Small State Types)
If your StateType has only a few properties, you could define getters directly in the class to avoid proxies entirely:
type StateType = { someVal: number; }; type AType = { state: StateType; doubleSomeVal(): number; } & StateType; class A implements AType { state: StateType; doubleSomeVal() { return this.state.someVal * 2; } // Add a getter for each StateType property get someVal() { return this.state.someVal; } constructor(state: StateType) { this.state = state; } }
This is simpler for small state shapes but doesn’t scale well if StateType has many properties—hence the proxy approach is better for flexibility.
内容的提问来源于stack exchange,提问作者Keir Lavelle

