我有以下场景:
class Dispatcher<R extends (...args: any) => any, T = undefined> {
fn: R
extra: T
constructor(fn: R, extra?: T) {
this.fn = fn;
this.extra = extra;
}
}
const test = new Dispatcher(() => {
return true;
});
// TS type hinting should know that extra is undefined
test.extra;
const test2 = new Dispatcher(() => {
return true;
}, {
graphUrl: "/foo/"
});
// TS type hinting should know that extra exists and has a property graphUrl
test2.extra.graphUrl
在本例中,我希望extra
类成员根据是否传递给构造函数来推断.如果我传递布尔值,它应该是布尔值,如果我传递字符串,它应该是字符串,如果我传递未定义,它应该是未定义的.现在推理工作正常,extra
个类型正确,但当我分配this.extra = extra
时,TS在构造函数代码中抛出了一个错误.严格地说,这个错误是有意义的,因为我将一个可以未定义的类型分配给一个不能定义的类型.问题是,如果我将成员定义更新为extra?: T
,那么推理就会中断,因为现在它认为extra类似于string | undefined
,这是不正确的.问题是额外的变量实际上不是"可选的",而是传递的值,该值可能未定义...这与可选的不同.
Type 'T | undefined' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to 'T | undefined'.
如果我修复了构造函数代码中的错误,那么类型推断就会停止工作,我得到的结果是string | undefined
,这是不准确的.我们之所以 Select know类型,是因为它被传递给了构造函数.