microsoft / microsoft/TypeScript
Generic constraints are "shallow", don't account for depth subtyping
还没有人认领这个 Issue。
- 主要语言
- Go
- 星标
- 111k
- 派生
- 14.3k
- 平均合并
- 2 天 4 小时
- 30 天内合并 PR
- 132
描述
🔎 Search Terms
ts1360 ts2322 generic fields , generic bound subtyping, generic constraint subtyping, could be instantiated with a different subtype of constraint, depth subtyping generics, parametric polymorphism depth subtyping
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the documentation for generics as of 5.9.2
⏯ Playground Link
💻 Code
Errors, as intended:
function safe<T extends string>(
name: string, // Unrelated to T.
): T {
return name // 'string' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'string'. (2322) 👍
}
Does not error, unexpectedly:
function unsafe<T extends { value: string }>(
name: string,
): T["value"] {
return name // No error. Why is this allowed?
}
// Example uncaught error:
unsafe<{ value: "cat" } | { value: "dog" }>(
"fish"
) satisfies "cat" | "dog"
🙁 Actual behavior
When T extends string, TypeScript correctly identifies that an arbitrary other string cannot be safely assigned to T, because T could be instantiated with any subtype of string.
When T extends { value: string }, TypeScript incorrectly allows an arbitrary other string to be assigned to T["value"], even though T could be instantiated with any subtype of { value: string }, and the depth subtyping rule for objects implies that the type of T["value"] is also a subtype of string.
🙂 Expected behavior
-
Both examples should fail with the same error. It should not be possible to return
namein the functionunsafe.More generally, TypeScript should be consistent in applying subtyping rules to generic constraints
T extends U. IfUis a primitive (likestringor"A" | "B") andTis checked as if it could be instantiated with any subtype ofU, then the same rule should apply whenUis an object type. -
If this is working as intended, the generics documentation should be updated to clarify that generic bounds are "shallow," and the correct approach is to use a second generic parameter.
Ideally this disclaimer could go under both the section on Generic Constraints (stipulating that only the top level parameter is treated as generic), as well as Using Type Parameters in Generic Constraints (to the effect of "note that this is the only way to handle this pattern").
Additional information about the issue
No response
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
从链接的 TypeScript Playground 开始,使用所示的 union 实例化来比较 generic string 示例和 indexed-access 示例。阅读 generics 文档中的 Generic Constraints 和 Using Type Parameters in Generic Constraints 部分。如果两个示例都收到相同的适当错误,或者文档清楚地解释了浅边界行为和第二参数方法,则视为完成。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- typescript
- 领域
- compilers
- Issue 类型
- 缺陷
- 难度
- 5/5
- 预计耗时
- 一周以上
- 活跃度
- 停滞
- 描述清晰度
- 基本清楚
- 新手友好度
- 35/100