在方法中使用 keyof 键入参数
In method use keyof to type parameter
假设您有以下 class:
class Foo {
protected callbacks: Callbacks = {};
bar(key: string) {
const callback = this.callbacks[key];
// do stuff with callback
}
...
}
回调 属性 可以通过其他方法更改(稍后)。
如何确保作为属性提供的键是回调的实际键 属性?
如果将回调实例传递给函数,我会这样做:
function bar<T, Key extends keyof T>(callbacks:T, key: Key) { ... }
但这不适用于 'this' 关键字。我知道在泛型中使用原始 this.callbacks 是不正确的,因为 this.callbacks 不是类型,而是实例。然而,用 typeof 转换它也不会产生结果..
class Foo {
protected callbacks: Callbacks = {};
bar<Key extends keyof typeof this.callbacks>(key: Key) { // Cannot find name 'this'
const callback = this.callbacks[key];
// do stuff with callback
}
...
}
我是不是遗漏了什么明显的东西?我的整个设计模式有缺陷吗?
要使这种模式可行,您需要 class 提前知道其 callbacks
属性 的确切键。我不知道 Callbacks
应该是什么类型,但它显然不够具体,无法满足您的要求?否则,您只需将 bar()
方法的 key
参数注释为 key: keyof Callbacks
.
假设没有特定的 Callbacks
类型适合您,而是您想使用不同的 callbacks
键创建不同的 Foo
实例,您应该使 Foo
成为 generic class,其中泛型类型参数(称之为 K
)对应于该实例的 callbacks
属性 的键的并集:
class Foo<K extends PropertyKey> {
constructor(protected callbacks: { [P in K]: () => void }) { }
bar(key: K) {
const callback = this.callbacks[key];
callback();
}
}
(在没有更多信息的情况下,我假设 callbacks
的所有属性都可以用零参数调用。)因为 callbacks
属性 具有函数值属性在 K
中的键处,那么 bar()
方法的 key
参数可以安全地为 K
。让我们来测试一下:
const foo = new Foo({
sayHello() { console.log("HELLO!") },
sayGoodbye() { console.log("GOODBYE!") }
})
foo.bar("sayHello"); // HELLO!
foo.bar("sayGoodbye"); // GOODBYE!
创建 foo
后,由于传入的回调对象,编译器将其推断为 Foo<"sayHello" | "sayGoodbye">
类型。因此 foo.bar()
只能用 [=32 调用=] 或 "sayGoodbye"
作为其参数。
假设您有以下 class:
class Foo {
protected callbacks: Callbacks = {};
bar(key: string) {
const callback = this.callbacks[key];
// do stuff with callback
}
...
}
回调 属性 可以通过其他方法更改(稍后)。
如何确保作为属性提供的键是回调的实际键 属性? 如果将回调实例传递给函数,我会这样做:
function bar<T, Key extends keyof T>(callbacks:T, key: Key) { ... }
但这不适用于 'this' 关键字。我知道在泛型中使用原始 this.callbacks 是不正确的,因为 this.callbacks 不是类型,而是实例。然而,用 typeof 转换它也不会产生结果..
class Foo {
protected callbacks: Callbacks = {};
bar<Key extends keyof typeof this.callbacks>(key: Key) { // Cannot find name 'this'
const callback = this.callbacks[key];
// do stuff with callback
}
...
}
我是不是遗漏了什么明显的东西?我的整个设计模式有缺陷吗?
要使这种模式可行,您需要 class 提前知道其 callbacks
属性 的确切键。我不知道 Callbacks
应该是什么类型,但它显然不够具体,无法满足您的要求?否则,您只需将 bar()
方法的 key
参数注释为 key: keyof Callbacks
.
假设没有特定的 Callbacks
类型适合您,而是您想使用不同的 callbacks
键创建不同的 Foo
实例,您应该使 Foo
成为 generic class,其中泛型类型参数(称之为 K
)对应于该实例的 callbacks
属性 的键的并集:
class Foo<K extends PropertyKey> {
constructor(protected callbacks: { [P in K]: () => void }) { }
bar(key: K) {
const callback = this.callbacks[key];
callback();
}
}
(在没有更多信息的情况下,我假设 callbacks
的所有属性都可以用零参数调用。)因为 callbacks
属性 具有函数值属性在 K
中的键处,那么 bar()
方法的 key
参数可以安全地为 K
。让我们来测试一下:
const foo = new Foo({
sayHello() { console.log("HELLO!") },
sayGoodbye() { console.log("GOODBYE!") }
})
foo.bar("sayHello"); // HELLO!
foo.bar("sayGoodbye"); // GOODBYE!
创建 foo
后,由于传入的回调对象,编译器将其推断为 Foo<"sayHello" | "sayGoodbye">
类型。因此 foo.bar()
只能用 [=32 调用=] 或 "sayGoodbye"
作为其参数。