Typescript 增加函数的类型签名';如果当前参数是函数且该函数具有属性,则为s参数

Typescript 增加函数的类型签名';如果当前参数是函数且该函数具有属性,则为s参数,typescript,Typescript,接受一个更好的标题的建议,代替这个,我正在概述我的确切用例 我正在编写一个库,它允许远程执行方法和访问序列化边界(如Web Worker)后面的属性 一般流程是通过一个属性/值“句柄”遍历源对象、函数和数组的形状,该句柄表示为IHandle接口 export interface IHandle<T> { property<K extends keyof T | ((...args: any) => any)>(key: K): K extends keyof T

接受一个更好的标题的建议,代替这个,我正在概述我的确切用例

我正在编写一个库,它允许远程执行方法和访问序列化边界(如Web Worker)后面的属性

一般流程是通过一个属性/值“句柄”遍历源对象、函数和数组的形状,该句柄表示为
IHandle
接口

export interface IHandle<T> {
  property<K extends keyof T | ((...args: any) => any)>(key: K): K extends keyof T ? IHandle<T[K]> : any;
  exec(
    ...args: T extends (...args: any) => any ? Parameters<T> : any
  ): T extends (...args: any) => any ? Promise<IHandle<ReturnType<T>>> : any;
  value(): T extends (...args: any) => any ? any : Promise<T>;
  dispose(): Promise<void>;
}
函数也可以传递基本属性

type Source = (foo: string) => foo
declare const handle: IHandle<Source>

const fooHandle: IHandle<string> = await handle.exec('foo')
const foo: string = await fooHandle.value()
我想看到的是:

const foo = await handle.exec(async (fooHandle: IHandle<string>) => {
    const foo = await fooHandle.value()
})
最后,有条件地了解
exec
param类型是否为回调,并根据需要对其进行更改

type Source = (one: string, cb: (prop: string) => any) => cb('foo')
declare const handle: IHandle<Source>

// Right now, fooHandle is a type string
const foo = await handle.exec('one', (fooHandle: IHandle<string>) => {
    //...
})
type Source=(一:字符串,cb:(prop:string)=>any)=>cb('foo'))
声明常量句柄:IHandle
//现在,foodhandle是一个类型字符串
const foo=await handle.exec('one',(foodhandle:IHandle)=>{
//...
})

我不知道我是否100%理解您的用例,尤其是当涉及到如何处理回调的返回类型时。。。现在我假设它保持不变。此外,我还感到困惑的是,
IHandle
即使在
T
与函数不同的情况下也会得到一个
exec()
方法。也就是说,如果有人接受
IHandle
并调用
exec()
方法,或者调用可能发生的任何其他边缘情况,我真的不知道您打算怎么做。既然你没有明确地询问这个问题,并且你的示例代码不测试这个问题,那么我将在以下问题的范围之外考虑这些问题。


我在这里的方法是编写一个类型别名
HandlifyParams
,它将非回调类型
T
单独保留,但将回调类型
T
转换为一个新的回调类型,其参数都封装在
IHandle
中,其返回类型单独保留(同样,不确定这是否是您想要的):

对于类型
T
(x:string,y:number)=>boolean
,编译器将使
exec(x:string,y:number)=>Promise
,因为
Handlify
Handlify
分别是
string
number
。但是对于一个类型
T
,比如
(x:string,f:(x:string)=>number)=>boolean
,编译器将使
exec(x:string,f:(x:IHandle)=>number)=>Promise
,因为
Handlify number>
将修改其输入成为
(x:IHandle)=>number


您可以验证示例测试现在编译时没有错误。万岁


我想我需要
推断
返回类型扩展了函数?我很难理解这一点。你能在打字游戏场上制作一个最小的可复制的例子吗?是的,对不起-我正在努力表达这个问题。我在示例底部添加了一个链接。谢谢,这很有帮助。但它似乎仍然不完整。
createHandle()
有什么作用?它只是
IHandle
的工厂函数。在上面的示例中,它基于其上方的源对象创建句柄。我将把这个问题改为使用与游乐场相同的语法,因为它更清晰,这正是我所需要的!我试图使用
keyof
语法,并用
Ihandle
包装键,但是我无法将其指定为回调类型的
…args
。谢谢你。您的代码示例还帮助我更好地理解了
expert
type Source = (cb: (prop: string) => any) => cb('foo')
declare const handle: IHandle<Source>
const foo = await handle.exec(async (fooHandle: IHandle<string>) => {
    const foo = await fooHandle.value()
})
/// fooHandle is the wrong type
const foo = await handle.exec(async (fooHandle: string) => {
    // ...
})
type Source = (one: string, cb: (prop: string) => any) => cb('foo')
declare const handle: IHandle<Source>

// Right now, fooHandle is a type string
const foo = await handle.exec('one', (fooHandle: IHandle<string>) => {
    //...
})
type HandlifyParams<T> = T extends (...args: infer A) => infer R ?
  (...args: { [I in keyof A]: IHandle<A[I]> }) => R : T;
export interface IHandle<T> {
  exec(
    ...args: (T extends (...args: infer A) => any ? {
      [I in keyof A]: HandlifyParams<A[I]>
    } : never)
  ): T extends (...args: any) => any ? Promise<IHandle<ReturnType<T>>> : any;
}