Conditional overloaded method call based on parameter value 打字稿编译错误 TS2322 TS2554

Conditional overloaded method call based on parameter value typescript compilation error TS2322 TS2554

我有一个函数将另一个函数作为参数。该参数根据另一个参数具有不同的签名。

我这样声明函数:

function edit({
    load, 
    onEdit
} : {
        load : true, 
        // options is way more complex in real life
        onEdit : (options : {a : number}) => void  
    } | {
        load : false, 
        onEdit : () => boolean 
    })
{ /* */ }

并想这样称呼它:

edit({
    load:true, 
    onEdit : ({a}) => {
        console.log('do something fun with a', a);
    }
}); 

// OR

edit({
    load:false, 
    onEdit : () => {
        return false; 
    }
})

我试着实现这样的方法:

function edit({
    load, onEdit
} : {
        load : true, 
        // options is way more complex in real life
        onEdit : (options : {a : number}) => void  
    } | {
        load : false, 
        onEdit : () => boolean 
    })
{
    let result : boolean; 
    if(load){
        const o = { a : 1 }; 
        onEdit(o); 
        result = true; 
    } else {
        // error TS2322: Type 'boolean | void' is not assignable to type 'boolean'.
        //  Type 'void' is not assignable to type 'boolean'.
        // error TS2554: Expected 1 arguments, but got 0. 
        result = onEdit(); 
    }
    console.log('result', result);
}

但是我收到这个错误

error TS2322: Type 'boolean | void' is not assignable to type 'boolean'.
Type 'void' is not assignable to type 'boolean'.

error TS2554: Expected 1 arguments, but got 0.

我尝试添加类型保护

    const shouldLoad = (fn: typeof onEdit): fn is (options: { a: number }) => void => {
        return load;
    };

但 id 没有帮助

如何实现类型安全的编辑方法?

typescript 代码对 typescript v4.6.2 有效,但对 v4.5.5 会产生错误。

这个问题有 3 种解决方案:

  1. 迁移到 typescript v4.6.2+

  2. 添加带有评论的@ts-ignore

     let result : boolean; 
     if(load) {
         const o = { a : 1 }; 
         onEdit(o); 
         result = true; 
     } else {
         // @ts-ignore - typescript issue with 4.5.5 
         result = onEdit(); 
     }
    
  3. 强制转换

     let result : boolean; 
     if(load) {
         const o = { a : 1 }; 
         onEdit(o); 
         result = true; 
     } else {
         // cast is required for typescript 4.5.5 
         result = (onEdit as () => boolean)(); 
     }