如何在 Typescript 中使用 ES6 代理?

VSD*_*kar 10 typescript

我想尝试一些有关代理的事情,但我很难让最简单的形式运行。

我有以下代码

const myObj = {
  x: 'Hello',
};

const p = new Proxy(myObj, {
  get: (target, key) => {
    return key in target ? target[key] + ' World!' : 'nope';
  },
});

console.log(p.x);
Run Code Online (Sandbox Code Playgroud)

我收到以下错误,但我不知道为什么以及如何解决它:

index.ts:7:28 - error TS7053: Element implicitly has an 'any' type because expression of type 'string | number | symbol' can't be used to index type '{ x: string; }'.
  No index signature with a parameter of type 'string' was found on type '{ x: string; }'.

7     return key in target ? target[key] + ' World!' : 'nope';
                             ~~~~~~~~~~~

Found 1 error.
Run Code Online (Sandbox Code Playgroud)

我认为TS应该能够推断出一切。我在这里想念什么?

小智 9

这是因为 被key定义为PropertyKey。这意味着它可能是string | number | symbol与只有一个 key 的对象不同的索引签名x。这并不是真正的类型错误 - TS 无法静态地确定您的对象不会被调用,x并且假设可能值的范围更广key。解决这个问题的一种方法是确保 TypeScript 它确实是一个keyof myObj,因为您已经自己进行了运行时检查:

return key in target ? target[key as keyof typeof target] + ' World!' : 'nope';
Run Code Online (Sandbox Code Playgroud)


VSD*_*kar 5

感谢 @Rafal2228 解释问题并提出解决方法。为了完整起见,我想发布我现在如何修复它。(带有 TypeGuard)

const hasKey = <T extends object>(obj: T, k: keyof any): k is keyof T =>
  k in obj;

const myObj = {
  x: 'Hello',
};

const p = new Proxy(myObj, {
  get: (target, key) => {
    return hasKey(target, key) ? target[key] + ' World!' : 'nope';
  },
});

console.log(p.x);
Run Code Online (Sandbox Code Playgroud)