我正在尝试将一些java库"翻译"为typescript。
public interface Expression<T> {
<R,C> R accept(Visitor<R,C> v, @Nullable C context);
}
public interface Constant<T> extends Expression<T> {
T getConstant();
}
public interface Visitor<R,C> {
R visit(Constant<?> expr, @Nullable C context);
}
到目前为止,我已经能够编码这个代码:
interface Expression<T> {
accept<R, C>(visitor: Visitor<R, C>, context: C) : R;
}
interface Constant<T> extends Expression<T> {
() : T;
}
public interface Visitor<R,C> {
(expr: Constant<any>, context: C): R; //<<<<?>>>>
}
我不知道如何翻译javaConstant<?>
。到目前为止,我已经把它翻译成Constant<any>
。
这是正确的吗?
[EDIT]
那么Interface<? super T>
和Interface<? extends T>
呢?
因为Constant的泛型参数T
没有出现在Visitor
接口定义中的任何位置,所以我想该类型中什么都不知道,什么都不需要——没有方法,没有属性。在这种情况下,空对象类型{}
就足够了——它几乎可以从任何其他类型中赋值。
interface Expression<T> {
accept<R, C>(visitor: Visitor<R, C>, context: C) : R;
}
interface Constant<T> extends Expression<T> {
() : T;
}
interface Visitor<R,C> {
(expr: Constant<{}>, context: C): R;
}
更新
与java类似,TypeScript支持泛型类型参数约束。很难发明一个现实但简单的例子来说明约束是真正必要的,所以这里是一个愚蠢的虚构例子:
interface Writer {
write(data: string): void;
}
interface WriterProvider<W extends Writer> {
getWriter(): W;
}
class C<W extends Writer> {
writer: W;
constructor(writerProvider: WriterProvider<W>) {
this.writer = writerProvider.getWriter();
}
writeAll(): void {
this.writer.write('a'); // here we can use its write() method
}
// supposedly something here should take advantage
// of knowing exact W type, as opposed to Writer, at compile time
}
然而,与java不同的是,typescript没有通配符泛型参数——Interface<? super T>
和Interface<? extends T>
没有等效参数。没有办法直接将这些代码翻译成TypeScript——你必须使用TypeScript习语,并根据具体情况找出表达你需要的最佳方式。
Java通用常见问题解答指出,在不需要或只需要部分了解参数化类型的类型参数的情况下,通配符是必要的。
TypeScript具有结构类型系统。这意味着,一旦有了关于类型的属性或方法的任何知识,就可以在这些知识足够的地方立即使用它。在实践中,没有必要向编译器声明您作为实际泛型参数传递的具体类型符合某些接口或约束——它自然带有结构类型,编译器能够自己解决。