假设我有一个包含许多方法的类,但我肯定知道它们的签名匹配。
是否可以在不描述此类的特定方法的情况下描述此类的接口?就像这里:
interface IController {
(input: string): number // any method without reference to its name
}
class Controller implements IController {
method1(input: string): number { ...do something }
method2(input: string): number { ...do something }
...
}
还是不可能?
答案 0 :(得分:3)
具有索引签名的选项(如他的答案中的@ fk82概述)具有不希望出现的结果,它迫使您向该类添加索引签名。这意味着您的类将可以由任意字符串索引,而这可能不是您想要的。
如果您的目标只是强制实现者类仅具有具有给定签名的方法,则更好的选择是使用映射类型:
type IController<K extends PropertyKey> = {
[P in K]: (input: string) => number;
}
class Controller implements IController<keyof Controller> {
method1(input: string): number { return input.length; }
method2(input: string): number { return input === '' ? 0 : 1; }
}
let a = new Controller();
a['aa'] // not allowwed under no implicit any
这具有一个额外的优点,即允许该类具有一些不符合签名要求的方法,但需要以显式方式进行:
class Controller implements IController<Exclude<keyof Controller, 'special'>> {
method1(input: string): number { return input.length; }
method2(input: string): number { return input === '' ? 0 : 1; }
special() { }
}
答案 1 :(得分:2)
您可以使用attrs
interface IController {
[name: string]: (input: string) => number;
}
一个小警告是TypeScript编译器现在将要求您将索引签名添加到实现IController
的每个类中。即您需要按以下方式定义Controller
类:
class Controller implements IController {
[name: string]: (input: string) => number;
method1(input: string): number { return input.length; }
method2(input: string): number { return input === '' ? 0 : 1; }
}
这是一个index signature,上面有完整的示例。请注意,索引签名将在断言中进行测试,例如
const A = {
m(input: string): number { return input.length; },
} as IController;
const B = {
m(input: string): string { return input; }
} as IController;
,由于返回值B
,分配string
将引发类型错误。
答案 2 :(得分:0)
根据@ FK82的回答,您可以修改某些内容以适合您所寻求的解决方案,但这将违反Interface构造的目的,该构造将对象绑定到一堆编译时已知的签名。引用接口时,编译器将如何知道您具体指的是什么方法?
但是,据我所知,为什么不尝试编写基于接口的解决方案,而不是在执行代码中声明功能抽象呢?只需描述一下函数签名,然后转换为合适的方法即可,因为在JS / TS中,函数是一等公民。
type Strategy = (input: string) => number;
class Controller implements IController {
method1(input: string): number { ...do something }
method2(input: string): number { ...do something }
}
function useMethod(f: Strategy): any {
...
const i = f('my string');
...
}
function main() {
const c = new Controller ();
const method = chooseOne === true ? c.method1 : c.method2;
useMethod (method);
}
这种处理方式与OOP中的Strategy Pattern不太相似,但是FP解决方案更精简,在我看来,它是Javascript / Typescript的更好功能之一。