Bug报告
🔎 搜索词
(所有搜索词都在标题中)
🕗 版本与回归信息
- 在版本4.2.3和4.3.5之间发生了变化
它仍然在4.7.4、4.8-beta和当前的夜间版本(4.8.0-dev.20220712)上运行。
⏯ Playground链接
带有相关代码的Playground链接
💻 代码
type Type = string | number
let obj: Record<string, Type> = {}
function test<T extends Type>(val: T): T {
if (0) {
// This typechecks but is wordier than needed.
obj['test'] = val;
return val;
}
// Nice and concise, but fails type checking.
return obj['test'] = val;
}
let string = test('hello') // should be fine
🙁 实际行为
类型检查失败。这似乎是因为表达式 obj['test'] = val
被赋予了更广泛的LHS( Type
)的类型,而不是RHS( T
)的更窄的类型。
🙂 预期行为
这应该能正确进行类型检查。考虑到赋值操作的RHS总是需要比LHS更窄,使用RHS似乎是最合理的选择。如果RHS是 any
的一个可能例外,可以回退到LHS。这对于与顶级代码保持一致也是很好的,因为在那里它似乎能正确工作。
4条答案
按热度按时间zaqlnxep1#
这应该能正确进行类型检查。考虑到赋值操作符的右侧总是比左侧更窄,
这里的底层逻辑是正确的,但问题在于这通常过于具体。例如:
fn
的返回类型是string[]
,因为我们使用了左侧的类型。如果我们使用了右侧的类型,它将是never[]
,这并不是你真正希望在程序中表现出来的类型。fcg9iug32#
我认为它没有按照预期工作,因为我手动示例化模板并用
string
替换T
时,它确实进行了类型检查。我做了更多的调查,意识到我对错误原因的认识是错误的。问题不在于它使用了赋值的左侧,而是它在
func<T extends WideTemplateType>
中使用了WideTemplateType
而不是精确的类型T
(不确定 TS 中这些术语的技术名称是什么)。这是一个更好的代码示例,与上一个Playground链接相同:我应该选择 A)更新此工单的描述和摘要以反映这些新信息,B)关闭此工单并打开一个新的干净工单,还是 C)两者都不做?
nkoocmlb3#
这有点奇怪。
z6psavjg4#
问题在于,它在
func<T extends WideTemplateType>
中使用了WideTemplateType
而不是精确的类型T
(不确定 TS 中的那些东西的技术名称是什么)。为了将来参考:
T
是一个 类型参数,而WideTemplateType
是它的 约束条件。