将类限制为仅包含具有特定签名的函数

时间:2018-12-03 17:49:18

标签: javascript typescript

在我的应用程序中,我有几个用于创建XML字符串的类。 每个类都有一些带有一些参数并返回字符串的方法。我想指定此限制,以便不能添加具有不同签名或其他类成员的方法。为此,这是我到目前为止的去处:

interface IRequestParser {
  [funcName: string]: (...args: any[]) => string;
}

和一个类的示例:

class myParser implements IRequestParser {
  [funcName: string]: (...args: any[]) => string;

  func1(a) {
    return '';
  }
}

这使我无法添加不返回字符串或任何其他非方法成员的函数,因此在myParser内不允许使用这些函数:

  a: string; // not allowed
  b() { // not allowed
    return 5;
  }

但是,这样做的效果是让我在没有警报的情况下从myParser实例调用任何函数名称:

const a = new myParser();
console.log(a.func1('a'));
console.log(a.func2(4, 5, ['s', 'b']));

func1的调用是有道理的,如果不为其参数a提供值,我也会得到一个错误。但是,我也可以调用不存在的函数func2和任何其他名称。

是否有办法既限制类成员的类型,又避免这种以任何名称调用任何函数的情况?

2 个答案:

答案 0 :(得分:3)

您使用的接口允许用任何字符串索引该类。我们无法通过界面来表达您想要的约束(至少我无法想到,也许其他人有想法)。

您可以使用函数将类限制为仅具有带有签名的函数,同时保留类具有的实际属性:

type ParserFn = (...args: any[]) => string;
function createRequestParserClass<
  T extends new (...a: any[]) => Record<keyof InstanceType<T>, ParserFn>>(ctor: T) {
  return ctor
}
const myParser = createRequestParserClass(class {
  // a: string; // not allowed
  // b() { // not allowed
  //   return 5;
  // }

  func1(a: string) {
    return '';
  }
});

type myParser = InstanceType

const a = new myParser();
console.log(a.func1('a'));
console.log(a.func2(4, 5, ['s', 'b'])); // error now 
console.log(a.func1(1)); // also error

答案 1 :(得分:3)

您也可以这样做:

class MyParser implements Record<keyof MyParser, (...args: any[]) => string> {

  // okay
  func1(a: any) {
    return '';
  }

  // error: string is not assignable to (...args: any[]) => string
  a: string; 

  // error: number is not assignable to string
  b() { 
    return 5;
  }
}

const myParser = new MyParser();
myParser.func1("okay"); // works
myParser.funcNope("huh"); // error, no property funcNope

允许实现一个具体的映射类型(例如Record<>),有时也可以使用循环引用(通常可以接受通过keyof来引用键)。

希望有所帮助;祝你好运!