是否可以在TypeScript中实现函数接口?

时间:2017-03-16 17:04:46

标签: typescript

我希望能够做到这一点

class MyFunc extends ((s: string) => boolean) { ... }

这样MyFunc的一个实例可以用作一个函数,它接受一个字符串作为输入并返回一个布尔值,如下所示:

const f = new MyFunc();
const b: boolean = f('someString');

这在TypeScript中是否可行?

在Scala等语言中,可以扩展类型String => Boolean,并提供apply方法来实现此目的。

class MyFunc extends (String => Boolean)
val f = new MyFunc()
val b: Boolean = f("someString")

5 个答案:

答案 0 :(得分:11)

也许你在考虑这样的事情?

interface FunctionInterface {
    (s: string): boolean;
}

const f: FunctionInterface = s => true;
const b: boolean = f('someString');

答案 1 :(得分:1)

TypeScript中没有默认的apply概念,但是有一些方法可以创建也是函数的类型对象。

interface MyCallable {
    (param1: string, param2: number): string;

    prop1: string;
    prop2: number;
    extraMethod: (param1: boolean) => boolean;
}

function makeMyCallable(prop1: string, prop2: number): MyCallable {
    let that = ((param1: string, param2: number) => param1 + param2) as MyCallable;

    that.prop1 = prop1;
    that.prop2 = prop2;
    that.extraMethod = (param1: boolean) => !param1;

    return that;
}

let mc = makeMyCallable("3", 4);

mc("3", 4);
mc.prop1 = "string";
mc.prop2 = 5;
mc.extraMethod(false);

答案 2 :(得分:1)

如果您的界面中只有此功能,则可以将其定义为

type FuncType = (s: string) => boolean;

一样使用它
const myFunc: FuncType;
function getFunction(): FuncType {}

答案 3 :(得分:0)

如果您只想要一个接受字符串并返回布尔值的简单函数,那么您就不需要使用类了。

const myFunc = (s: string): boolean => {
  return s !== "";  //whatever logic is needed here
};

但是,是的,您可以在TypeScript中扩展类

class MyBaseClass {
  constructor() { }

  public doThing = (s: string): boolean => {
    return s !== "";  //whatever logic is needed here
  }
}

class MyFunc extends MyBaseClass {
  constructor() {
    super();
  }
}

const f = new MyFunc();
const b = f.doThing("hi"); //returns a boolean

更新了对评论的回复

如下面的另一个答案所述,你不能真正new一个类,将该实例分配给一个变量,然后将其作为一个函数调用。你可以在创作上做到这一点,就像这样:

class MyBaseClass {
  constructor() { }

  public doThing = (s: string): boolean => {
    return s !== "";  //whatever logic is needed here
  }
}

class MyFunc extends MyBaseClass {
  constructor(private s: string) {
    super();
    this.doThing(this.s);
  }
}

const f = new MyFunc("hi"); //returns a boolean

您可以使用上面的代码on the Typescript playground here

答案 4 :(得分:0)

取决于用例。这里有几种方法。 https://typescriptlang.org/play/...

我们以某种方式导入

type fInterface = (...params: fArgs) => fRet
  • 作为单独的类型
type fArgs = [number, string]
type fRet = boolean

没关系-它们可以与ParametersReturnType

互换

我们实现的函数错误

function nop() {}
  1. 手动选择参数类型
function isEqual0(x: fArgs[0], y: fArgs[1]): fRet {
  //return x == y //TS-ERROR: This condition will always return 'false' since the types 'number' and 'string' have no overlap.ts(2367)
  return `${x}` == y
}
  1. 使用destructing
function isEqual1(...args: fArgs): fRet {
  const [x, y] = args
  return `${x}` == y
}
  1. 使用overload。用法严格,但在实施过程中,所有参数均为any
function isEqual2(...args: Parameters<fInterface>): ReturnType<fInterface>
function isEqual2(x: any, y: any) {
  return x == y
}
  1. 毕竟,我们可以通过重新键入来验证(例如typing-the-function)。在任何情况下,父模块中都将进行类型验证。
function isEqual3(x: any, y: any) {
  const valid: typeof  isEqual3 extends fInterface ? true : never = true
  if (!valid)
    throw Error()
  return x == y
}

const _exports = {
  isEqual0, isEqual1, isEqual2, isEqual3, nop
}
, _exportCheck = _exports as  Record<keyof typeof _exports, fInterface> //TS-ERROR The types returned by 'nop(...)' are incompatible between these types.

module.exports = _exportCheck
export default _exportCheck
export {
  isEqual0, isEqual1, isEqual2, nop
}

有很多方法可以解决TS-Error问题。