【问题标题】:Typescript limitation workaround打字稿限制解决方法
【发布时间】:2019-06-02 13:18:11
【问题描述】:

我有一个代码,从人类的角度来看是完全可以的。但看起来打字稿类型系统很难理解它。 有没有一种聪明的方法来提示编译器该行中的一切都很好

  const isMustToRun: boolean = isFunc(condition) ? condition() : condition;

代码:

    export const noop = function() {
    };

    export const isFunc = function(obj: any): boolean {
      return typeof obj === 'function';
    };

    /**
     *
     * @param func funtion to run
     * @param condition condition check
     * @param args
     */
    export const runIf = function f(condition: (Function | boolean), func: Function, ...args: any[]) {
      return () => {
        const isMustToRun: boolean = isFunc(condition) ? condition() : condition;
        return isMustToRun ? func(...args) : noop();
      };
    };

如果我写了

typeof condition === 'function'

而不是“isFunc”调用,然后它可以工作。但我不想重复代码..

【问题讨论】:

  • 您遇到的错误是什么?您的参数类型声明不包括返回值类型。
  • @Pointy 无法调用其类型缺少调用签名的表达式。输入'布尔| Function' 没有兼容的调用签名。

标签: javascript typescript functional-programming


【解决方案1】:

改变返回类型

export const isFunc = function(obj: any): boolean {
  return typeof obj === 'function';
};

成为is Function

export const isFunc = function(obj: any): obj is Function {
  return typeof obj === 'function';
};

更多

这叫user defined type guard?

【讨论】:

  • 这就是我想要的。感谢您向我指出文档 :-)
  • 还要注意 typeof condition === 'function' ? condition() : condition 会编译,因为 TS 理解 typeof 类型保护。
【解决方案2】:

您需要在自定义类型保护中转换isFunc,您的代码将按预期工作。:

export const isFunc = function(obj: any): obj is Function {
  return typeof obj === 'function';
};

我建议不要使用Function,尽管它不是非常安全的类型,您可以使用函数签名加强函数类型,并使用Extract 条件类型来保留传入的实际类型isFunc type-guard 的函数:

export const isFunc = function<T>(obj: T): obj is Extract<T, Function> {
    return typeof obj === 'function';
};

export const runIf = function f(condition: ((()=> boolean) | boolean), func: Function, ...args: any[]) {
    return () => {
        const isMustToRun: boolean = isFunc(condition) ? condition() : condition;
        return isMustToRun ? func(...args) : noop();
     };
};

或者是runIf 的完全类型安全版本,它检查argsfunc 参数:

export const runIf = function f<T extends (...a: any)=>any>(condition: ((()=> boolean) | boolean), func: T, ...args: Parameters<T>): (()=>ReturnType<T>) {
    return () => {
    const isMustToRun: boolean = isFunc(condition) ? condition() : condition;
        return isMustToRun ? func(...args as any[]) : noop();
    };
};

function testFn(n: string) : number { return +n;}
runIf(true, testFn, "0"); //ok
runIf(true, testFn, 0); //err

【讨论】:

  • 没有必要缩小范围。 TypeScript 不会将类型扩大到 Function。原始定义将被保留。尝试针对declare const foo: typeof addEventListener | null; if (isFunc(foo)) foo() 运行您的第一个答案。
猜你喜欢
  • 2021-08-21
  • 1970-01-01
  • 1970-01-01
  • 2016-09-03
  • 1970-01-01
  • 2021-06-19
  • 2021-08-10
  • 2018-06-25
  • 2016-11-12
相关资源
最近更新 更多