我正在通过嵌入到第三方软件 API 的 JS 创建一个 TS 包装器,该 API 不受我管理。我想在类型和接口中捕获尽可能多的行为,因为无类型的 vanilla JS 在我的情况下很难让它工作。
所以,更具体地说:
我有外部对象,并且我有一个接口,它声明了它具有的功能
declare var foo: object
interface FooContract {
function doFooStuff: (fooParam: string) => BlaError | Success
function doBarStuff: (barParam: string) => BlaError | Success
}
我想检查一下:
- 给定对象
foo
具有字段doFooStuff
和doBarStuff
。 - 这些字段是函数。
- 这些函数采用我描述的参数,如果不返回有意义的错误消息,至少检查 arity。
- 这些函数返回返回类型中描述的数据,如果没有返回有意义的错误消息。
所以我实际上确实理解 3) 和 4) 几乎是运行时检查,应该通过测试来验证,但无论如何。
有时 API 会抛出一些错误,我想以某种方式描述和指示将返回哪个错误。错误主要是字符串和 POJO,我想为它们分配类型(最好是名义上的,以任何数量的轮子重新发明和肮脏的黑客为代价)。
到目前为止,我来到:
declare var foo: object
interface FooContract {
function doFooStuff: (fooParam: string) => BlaError | Success
function doBarStuff: (barParam: string) => BlaError | Success
}
function isFooContract(x: object): x is FooContract {
const r = x as FooContract
return r.doFooStuff !== undefined && (typeof r.doFooStuff) == "function" &&
r.doBarStuff && (typeof r.doFooStuff) == "function"
}
class FooOps {
private fooInternal: FooContract
constructor (_inner: object) {
if(isFooContract(_inner))
this.fooInternal = _inner
else
throw new EverythingIsBrokenException(_inner, "foo object not satisfies listed asserts")
}
function doFooStuff(fooParam: string): BlaError | Success {
const ret = this.fooInternal(fooParam)
if(isBlaError(ret))
return ret
else if (isSuccess)
return ret
else
throw new EverythingIsBrokenException(ret, "Returned value of Foo.doFooStuff is not error nor success but something unexpected")
}
}
所以根本没有 3),我需要手写大量的样板。是否有某种代码生成/编译器宏扩展/编译时反射工具来检查字段是否存在?