如何根据方法中另一个参数的属性值设置类型?相对来说,我是TypeScript的新手。
这就是我试过的:
class SomeClass {
// constructor, other properties, etc
listen<K extends keyof ClientEvents>({ event: K }: ClientEvent, listener: (...args: ClientEvents[K]) => any)
}在这里,ClientEvents看起来像这样:
interface ClientEvents {
"event-1": [data: number]
"event-2": [data: number]
"event-3": [data: any]
}ClientEvent (no s)看起来如下:
interface ClientEvent {
event: keyof ClientEvents
anotherProperty: any // I don't want to share all the properties
}目前,event字段对event-1进行自动填充,但是函数的第一个参数显示为any类型,但应该是number类型。我如何在不需要更多参数的情况下修复这个问题?
当将data之一从ClientEvents内部更改为string类型时,它将显示为string | number类型。
class SomeClass {
listen<K extends keyof ClientEvents>({ event: K }: ClientEvent, listener: (...args: ClientEvents[K]) => any): void;
}
interface ClientEvents {
"event-1": [data: number]
"event-2": [data: string]
}
interface ClientEvent {
event: keyof ClientEvents
anotherProperty: any
}
new SomeClass().listen({
event: "event-1",
anotherProperty: 1
}, (arg) => {
arg // type is string | number
})这是一个操场连接
发布于 2022-01-20 19:04:41
有关可能的权威答案,请参见解构赋值和类型注释的常见问题条目。
您的问题是,K in { event: K }: ClientEvent不是您所认为的那样。在K中,如果您有一个像{ event: K }这样的函数参数,那么您将使用用变量重命名破坏赋值,因此您将将该函数参数的event属性复制到名为event的变量中。
function foo({event: K}: ClientEvent) {
// variable -----> ^
console.log(K.toUpperCase());
// ^ <---- see?
}
foo({event: "event-1", anotherProperty: 123}) // EVENT-1因为JavaScript支持这一点,所以TypeScript也支持这一点(正如您可以从ClientEvent 类型注释看到的那样),因此调用签名本身只是使用K作为它忽略的虚拟参数名称。
当然,该K不能用作同名类型参数K的推断站点,因为它们是无关的。
您试图使用K作为event属性的类型注释。但这是不支持的。事实上,目前还没有办法将类型注释放在析构对象本身中。微软/打字稿#29526上有一个开放的特性请求,要求采取某种方法(也许.双冒号?但就目前而言,这是不可能的。
如果您想给event属性提供一个类型,则必须在实际的类型注释中在析构对象之后执行该类型:
{ event }: { event: K }如果您想要保留整个事物需要是一个ClientEvent这一事实,您需要用类似于相交类型的东西来表示这一点。
{ event }: { event: K } & ClientEvent或者可能通过扩展您的ClientEvent接口,如果看起来更好的话:
interface ClientEventFor<K extends keyof ClientEvents> extends ClientEvent {
event: K
}
declare class SomeClass {
listen<K extends keyof ClientEvents>(
{ event }: ClientEventFor<K>,
listener: (...args: ClientEvents[K]) => any): void;
}然后事情就会开始对你起作用:
new SomeClass().listen(
{ event: "event-1", anotherProperty: 1 },
(arg) => { arg.toFixed() } // okay, arg is number here
)发布于 2022-01-20 18:08:04
在接口中使用类型参数的解决方法
export interface ClientEvent<L = keyof ClientEvents> {
event: L,
site: string
}
export class SomeClass {
listen<K extends keyof ClientEvents>({ event }: ClientEvent<K>, listener: (...args: ClientEvents[K]) => any): SomeClass
}和JavaScript代码:
let a = new Client()
a.listen({
event: "event-2"
}, (a) => {
a
})说a是一个字符串,所以它工作得很完美。
https://stackoverflow.com/questions/70789912
复制相似问题