【问题标题】:Need to specify type of an overloaded function using property of an interface需要使用接口的属性来指定重载函数的类型
【发布时间】:2021-08-27 18:13:15
【问题描述】:

我需要使用接口的属性指定函数的类型(通常需要使用接口定义模块的 API),但是 ts 抱怨返回类型,似乎它只考虑了一种类型定义,因为抱怨返回不正确类型:

export interface DateWrapper {
    isSame(firstDate: DateType, secondDate: DateType): boolean;
    isSame(firstDate: DateType): (secondDate: DateType) => boolean;
}

export const isSame: DateWrapper['isSame'] = (
    firstDate: DateType,
    secondDate?: DateType,
) => {
    if (!secondDate) {
        return (secondDate_: DateType) =>
          areDatesEqueal(firstDate, secondDate_);
    }

    return areDatesEqueal(firstDate, secondDate);
};

这是来自 ts 的错误:

Type 'boolean | ((secondDate_: DateType) => boolean)' is not assignable to type 'boolean'

使用function declaration 指定重载可以解决问题,但我需要使用接口属性

【问题讨论】:

    标签: typescript function interface overloading


    【解决方案1】:

    似乎没有一种干净的方法可以为具有不同返回类型的箭头函数指定重载。 SO上有很多示例,其中返回类型相同,或者 any 在返回值的函数中。鉴于此,这里有 3 个不太理想的建议,它们在整洁度和类型正确性方面各不相同。

    只需使用类型断言。这里的缺点是,如果 DateWrapper.isSame 的定义发生更改,则会引入错误。一般来说,如果可以的话,最好避免类型断言。

    export const isSame = ((firstDate: DateType, secondDate?: DateType) => 
      (secondDate == null) 
        ? (secondDate_: DateType) => areDatesEqueal(firstDate, secondDate_)
        : areDatesEqueal(firstDate, secondDate)
    ) as DateWrapper['isSame'];
    

    另一种方法是声明重载函数并将其分配给变量。与第一个解决方案不同,如果 DateWrapper.isSame 的定义发生变化,那么在这些函数被重构以匹配之前,您将无法构建。缺点是这个函数存在于一定范围内,可能会引起混淆。

    function isSameFn(firstDate: DateType, secondDate: DateType): boolean;
    function isSameFn(firstDate: DateType): (secondDate: DateType) => boolean;
    function isSameFn(firstDate: DateType, secondDate?: DateType) {
      return (secondDate == null) 
        ? (secondDate_: DateType) => areDatesEqueal(firstDate, secondDate_)
        : areDatesEqueal(firstDate, secondDate);
    }
    export const isSame: DateWrapper['isSame'] = isSameFn;
    

    为了避免污染某些范围,您可以将函数包装在返回 isSame 函数的自动执行函数中。虽然这是最丑陋的,但它没有任何先前解决方案的问题。

    export const isSame: DateWrapper['isSame'] = (() => {
      function isSameFn(firstDate: DateType, secondDate: DateType): boolean
      function isSameFn(firstDate: DateType): (secondDate: DateType) => boolean
      function isSameFn(firstDate: DateType, secondDate?: DateType) {
        return (secondDate == null) 
          ? (secondDate_: DateType) => areDatesEqueal(firstDate, secondDate_)
          : areDatesEqueal(firstDate, secondDate);
      }
      return isSameFn;
    })();
    

    【讨论】:

    • 不幸的是,没有一个建议的解决方案适合我,你描述的第一个解决方案的缺点是关于第二个它看起来像我的案例的开销。不幸的是,您是对的,似乎没有“明确”的方法来实现目标。感谢您的详细解释!
    【解决方案2】:

    下面的解决方案涵盖了我的情况,也许它对其他人有用:

    export interface DateWrapper {
       isSame: typeof isSame;
    }
    
    export function isSame (firstDate: DateType, secondDate: DateType): boolean
    export function isSame (firstDate: DateType): (secondDate: DateType) => boolean;
    export function isSame (firstDate: DateType, secondDate?: DateType) {
        if (!secondDate) {
            return (secondDate_: DateType) => areDatesEqueal(firstDate, secondDate_);
        }
    
        return areDatesEqueal(firstDate, secondDate);
    };
    

    【讨论】:

      猜你喜欢
      • 2012-04-12
      • 1970-01-01
      • 2011-09-08
      • 1970-01-01
      • 2017-11-24
      • 2014-08-22
      • 2017-09-16
      • 2022-12-08
      • 2012-10-26
      相关资源
      最近更新 更多