【发布时间】:2019-08-04 03:32:12
【问题描述】:
我正在尝试创建一个通用函数,它接受基类的子类型,并返回一个解析为指定类的实例的承诺。这个例子展示了我想要实现的目标:
class foo {}
class bar extends foo {}
const someBar = new bar();
function foobar<T extends foo>(): Promise<T> {
return new Promise<T>(resolve => resolve(someBar)); // this doesn't compile
}
我意识到 TypeScript 正在使用结构类型,因此在这个简单的示例中它将接受 T 的任何类型。但我不确定为什么它不允许我返回 someBar 的值。
有没有办法实现我在这里尝试做的事情?谢谢!
我得到的编译器错误是:
const someBar: bar
Argument of type 'bar' is not assignable to parameter of type 'T | PromiseLike<T> | undefined'.
Property 'then' is missing in type 'bar' but required in type 'PromiseLike<T>'.ts(2345)
lib.es5.d.ts(1393, 5): 'then' is declared here.
更新
根据要求,这里有一些关于我要完成的工作的附加信息。这段代码编译得很好(我在 foo 和 bar 中添加了函数,只是为了在结构上区分它们):
class foo {
f() {}
}
class bar extends foo {
b() {}
}
const someBar = new bar();
function foobar(): Promise<foo> {
return new Promise<foo>(resolve => resolve(someBar));
}
foobar().then(result => {
const myBar: bar = result as bar;
console.log(myBar);
});
我试图避免需要向下转换 promise-const myBar: bar = result as bar 的多态结果,如下所示:
class foo {
f() {}
}
class bar extends foo {
b() {}
}
const someBar = new bar();
function foobar<T extends foo>(): Promise<T> {
return new Promise<T>(resolve => resolve(someBar));
}
foobar<bar>().then(result => {
const myBar: bar = result;
console.log(myBar);
});
TS 正确推断结果是一个条形,但它不允许我在函数中返回 someBar。
我已经能够在我的泛型类方法处理this 的类中使用多态this 来实现这一点 - 但这里我不在课堂上。
更新 2
实际上,这不需要承诺来说明我在做什么。在这里,我进一步简化了(并省略了 foo 和 bar 的定义,因为它没有改变):
function foobar<T extends Foo>(): T {
return someBar;
}
const mybar: Bar = foobar<Bar>();
而且,这就是我在“纯 javascript”中所做的:
var someBar = new bar();
function foobar() {
return someBar;
}
var myBar = foobar();
如您所见,我所做的只是微不足道的。我只是想在不向下转换的情况下进行多态类型检查。
【问题讨论】:
-
这是对泛型的常见误解。通用参数由函数的调用者决定。这些函数无法决定泛型参数是什么。通过在此处返回
someBar,您的函数假定T是bar,它不一定是。 -
我想我不明白约束的作用,如果它不约束类型 =)
-
它正在限制类型。您不能使用 any
T调用该方法。泛型约束不约束方法实现(它实际上允许你在实现中做更多事情),而是调用者。 -
@EricS 如果你用纯 javascript 编写这个函数,代码会是什么? (您提供了描述,但它与您提供的代码并不真正匹配)如果我们知道 javascript,我们也许可以帮助您向其中添加类型信息。
-
嗨@NicholasTower - 我不确定纯javascript在这里会有所帮助,因为我只是使用一个简单的承诺 - 但试图实现多态静态类型安全。但我确实在上面编辑了我的问题,并展示了一个有效的非通用版本。这个版本要求我向下转换结果。我试图避免沮丧。这有意义吗?
标签: typescript generics