TypeScript:如何委托接口方法
TypeScript: How to delegate interface methods
我有一个来自第三方库的类似这样的界面:
MyInterface{
foo(arg: string): Promise<any>;
foo(arg: string, ...params: any[]): Promise<any>;
foo<T>(arg: string): Promise<T>;
foo<T>(arg: string, ...params: any[]): Promise<T>;
bar(arg: string, callback?: (err: Error, row: any) => void): Promise<number>;
bar(arg: string, ...params: any[]): Promise<number>;
}
我想将接口方法委托给相同类型的实现,如下所示:
MyClass implements MyInterface {
private impl:MyInterface = ...
foo(..) //how to do it right ??
// TS2393: Duplicate function implementation.
bar(arg: string, callback?: (err: Error, row: any) => void): Promise<number>{
return impl.bar(sql,callback);
}
// TS2393: Duplicate function implementation.
bar(arg, ...params: any[]): Promise<number>{
return impl.bar(arg,params);
}
}
我不知道如何正确实现委托,所以调用了正确的 impl
方法。
都没有TypeScript function overloading
也没有 Is there a way to do method overloading in TypeScript?
正在帮助我做出正确的授权。
不是最佳解决方案,但仍有一些解决方法:
interface MyInterface {
foo(arg: string): string
foo(arg: number): number
}
class Foo implements MyInterface {
foo(arg: string): string;
foo(arg: number): number;
// foo(arg: number): string; -> error, if you uncomment this line, please comment line above
foo(arg: string | number) {
if (typeof arg === 'string') {
return arg
}
return 12 as number
}
}
const result = new Foo().foo(2)
坏消息:您应该编写所有重载。据我所知,用重载映射接口是不可能的
好消息:如果你提供与实现的接口不兼容的函数重载,TS 会抱怨。
更新
还有另一种方法。
您可能不需要将 Foo
class 扩展 MyInterface
。
interface MyInterface {
foo(arg: string): string
foo(arg: number): number
}
class Foo {
foo(arg: string): string;
foo(arg: number): number;
foo(arg: string | number) {
if (typeof arg === 'string') {
return arg
}
return 12 as number
}
}
// sorry, I can't find the link to the author of this type utility
type DeepEqual<X, Y> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? true : false;
/**
* Here you can just check if types are deep equal or not
* Try to change overloadings for `foo` method and you
* will see that Result type will be falsy
*/
type L = Deep<Foo, MyInterface>
当方法调用应该委托给类似的方法签名时,委托的方法可以决定如何处理给定的参数。
重载方法签名归结为最通用的重载(与静态类型语言有些不同)。因此,不需要实现接口中声明的更具体的方法,但可以在实现接口的 class 中包含声明作为编译器提示。在这种情况下,rest 又名 vararg 参数 (...arg:any[]
) 派上用场,因为它呈现通用方法签名。
class MyClass implements MyInterface {
constructor(private delegate:MyInterface){}
// these 2 methods below can't be declared in this class since they have
// the same signature as the ones with <T> type argument (type-erasure?)
// foo(arg: string, ...params: any[]): Promise<any>;
// foo(arg: string): Promise<any>;
//compiler hint, the method below will be called at runtime
foo<T>(arg: string): Promise<T>;
foo<T>(arg: string, ...params: any[]): Promise<T>{
//we leave the responsibility to handle the given arguments to the `delegate` implementation
return this.delegate.foo(arg, ...params);
}
// this method declaration has no implicit implementation, at runtime
// the more generic method below will be called, this method acts
// as a compiler "hint" and can be ommitted
bar(arg: string, callback?: (err: Error, row: any) => void): Promise<number>;
bar(arg, ...params: any[]): Promise<number>{
return this.delegate.bar(arg,params);
}
}
我有一个来自第三方库的类似这样的界面:
MyInterface{
foo(arg: string): Promise<any>;
foo(arg: string, ...params: any[]): Promise<any>;
foo<T>(arg: string): Promise<T>;
foo<T>(arg: string, ...params: any[]): Promise<T>;
bar(arg: string, callback?: (err: Error, row: any) => void): Promise<number>;
bar(arg: string, ...params: any[]): Promise<number>;
}
我想将接口方法委托给相同类型的实现,如下所示:
MyClass implements MyInterface {
private impl:MyInterface = ...
foo(..) //how to do it right ??
// TS2393: Duplicate function implementation.
bar(arg: string, callback?: (err: Error, row: any) => void): Promise<number>{
return impl.bar(sql,callback);
}
// TS2393: Duplicate function implementation.
bar(arg, ...params: any[]): Promise<number>{
return impl.bar(arg,params);
}
}
我不知道如何正确实现委托,所以调用了正确的 impl
方法。
都没有TypeScript function overloading 也没有 Is there a way to do method overloading in TypeScript? 正在帮助我做出正确的授权。
不是最佳解决方案,但仍有一些解决方法:
interface MyInterface {
foo(arg: string): string
foo(arg: number): number
}
class Foo implements MyInterface {
foo(arg: string): string;
foo(arg: number): number;
// foo(arg: number): string; -> error, if you uncomment this line, please comment line above
foo(arg: string | number) {
if (typeof arg === 'string') {
return arg
}
return 12 as number
}
}
const result = new Foo().foo(2)
坏消息:您应该编写所有重载。据我所知,用重载映射接口是不可能的
好消息:如果你提供与实现的接口不兼容的函数重载,TS 会抱怨。
更新
还有另一种方法。
您可能不需要将 Foo
class 扩展 MyInterface
。
interface MyInterface {
foo(arg: string): string
foo(arg: number): number
}
class Foo {
foo(arg: string): string;
foo(arg: number): number;
foo(arg: string | number) {
if (typeof arg === 'string') {
return arg
}
return 12 as number
}
}
// sorry, I can't find the link to the author of this type utility
type DeepEqual<X, Y> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? true : false;
/**
* Here you can just check if types are deep equal or not
* Try to change overloadings for `foo` method and you
* will see that Result type will be falsy
*/
type L = Deep<Foo, MyInterface>
当方法调用应该委托给类似的方法签名时,委托的方法可以决定如何处理给定的参数。
重载方法签名归结为最通用的重载(与静态类型语言有些不同)。因此,不需要实现接口中声明的更具体的方法,但可以在实现接口的 class 中包含声明作为编译器提示。在这种情况下,rest 又名 vararg 参数 (...arg:any[]
) 派上用场,因为它呈现通用方法签名。
class MyClass implements MyInterface {
constructor(private delegate:MyInterface){}
// these 2 methods below can't be declared in this class since they have
// the same signature as the ones with <T> type argument (type-erasure?)
// foo(arg: string, ...params: any[]): Promise<any>;
// foo(arg: string): Promise<any>;
//compiler hint, the method below will be called at runtime
foo<T>(arg: string): Promise<T>;
foo<T>(arg: string, ...params: any[]): Promise<T>{
//we leave the responsibility to handle the given arguments to the `delegate` implementation
return this.delegate.foo(arg, ...params);
}
// this method declaration has no implicit implementation, at runtime
// the more generic method below will be called, this method acts
// as a compiler "hint" and can be ommitted
bar(arg: string, callback?: (err: Error, row: any) => void): Promise<number>;
bar(arg, ...params: any[]): Promise<number>{
return this.delegate.bar(arg,params);
}
}