如何使用 `typeof Node<T>` 的泛型类型?
How to use a generic type with `typeof Node<T>`?
假设我们有一些 Java Node
、StringNode
和 NodeFactory
类:
public class Node<T> {
private T value;
public void init(T value){
this.value = value;
}
}
public class StringNode extends Node<String> {}
public class NodeFactory {
public static <T> Node<T> createNode(Class<? extends Node<T>> nodeClass, T value) throws Exception {
Node<T> node = nodeClass.getConstructor().newInstance();
node.init(value);
return node;
}
}
因此 NodeFactory.createNode(StringNode.class, "value1");
将创建一个 StringNode
,其值为:"value1"
.
我怎么能用打字稿写这样一个工厂方法?
我试着用打字稿写了一个工厂方法:
public static createNode<T>(NodeClass: typeof Node<T>, value: T): Node<T> {
const node = new NodeClass();
node.init(value);
return node;
}
但不接受 typeof Node<T>
通用类型。所以我尝试输入方法的类型参数:
public static createNode<T, N extends Node<T>>(NodeClass: typeof N, value: T): Node<T> {
但编译器也不接受:typeof N
: TS2693: 'N' only refers to a type, but is being used as a value here
有没有一种类型安全的方法可以在打字稿中编写这样的工厂方法?
我找到了解决方案:
public static createNode<N extends { new(): Node<T> }, T>(NodeClass: N, value: T): Node<T> {
显然我只需要 N 来实现带有 new(): Node<T>
方法(或构造函数)的接口。
class 的通用参数适用于 实例 而不是静态 class 本身。 value
也用于实例。所以 NodeClass
需要是一个“可更新的”类型,即 returns 具有正确泛型的实例。
这意味着这会起作用:
function createNode<T>(NodeClass: { new (): MyNode<T> }, value: T): MyNode<T> {
const node = new NodeClass();
node.init(value)
return node;
}
测试:
// good
const a = createNode(StringNode, "asd")
const b = createNode(NumberNode, 123)
const c = createNode(FunctionNode, () => 'hello world')
const d = createNode(MyNode, true) // MyNode<boolean>
// error, as expected
const bad = createNode(StringNode, 123)
createNode(MyNode, true)
是一个很好的奖励。 Typescript 从第二个参数中获取 T
,并将其放入 NodeClass
中。
假设我们有一些 Java Node
、StringNode
和 NodeFactory
类:
public class Node<T> {
private T value;
public void init(T value){
this.value = value;
}
}
public class StringNode extends Node<String> {}
public class NodeFactory {
public static <T> Node<T> createNode(Class<? extends Node<T>> nodeClass, T value) throws Exception {
Node<T> node = nodeClass.getConstructor().newInstance();
node.init(value);
return node;
}
}
因此 NodeFactory.createNode(StringNode.class, "value1");
将创建一个 StringNode
,其值为:"value1"
.
我怎么能用打字稿写这样一个工厂方法?
我试着用打字稿写了一个工厂方法:
public static createNode<T>(NodeClass: typeof Node<T>, value: T): Node<T> {
const node = new NodeClass();
node.init(value);
return node;
}
但不接受 typeof Node<T>
通用类型。所以我尝试输入方法的类型参数:
public static createNode<T, N extends Node<T>>(NodeClass: typeof N, value: T): Node<T> {
但编译器也不接受:typeof N
: TS2693: 'N' only refers to a type, but is being used as a value here
有没有一种类型安全的方法可以在打字稿中编写这样的工厂方法?
我找到了解决方案:
public static createNode<N extends { new(): Node<T> }, T>(NodeClass: N, value: T): Node<T> {
显然我只需要 N 来实现带有 new(): Node<T>
方法(或构造函数)的接口。
class 的通用参数适用于 实例 而不是静态 class 本身。 value
也用于实例。所以 NodeClass
需要是一个“可更新的”类型,即 returns 具有正确泛型的实例。
这意味着这会起作用:
function createNode<T>(NodeClass: { new (): MyNode<T> }, value: T): MyNode<T> {
const node = new NodeClass();
node.init(value)
return node;
}
测试:
// good
const a = createNode(StringNode, "asd")
const b = createNode(NumberNode, 123)
const c = createNode(FunctionNode, () => 'hello world')
const d = createNode(MyNode, true) // MyNode<boolean>
// error, as expected
const bad = createNode(StringNode, 123)
createNode(MyNode, true)
是一个很好的奖励。 Typescript 从第二个参数中获取 T
,并将其放入 NodeClass
中。