Reverse mapped types don't use their constraint types when no candidates are present unlike the regular type parameters

未关闭
#56,241 1 条评论 2 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
5/5
预计耗时
一周以上
新手友好度
30/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
停滞
技术栈
typescript
领域
compilers

调研方向

从 Playground 复现开始,跟踪报告中列出的类型检查路径:getInferredType、inferReverseMappedType 和 getTypeFromInference。调查在 reverse-mapped 推断没有候选项时如何处理约束类型;完成的标准是,提供的 setup 调用能够成功推断,且不会出现所示的约束错误。

由索引模型根据 Issue 内容生成。

描述

Domain: Mapped Types Possible Improvement
🔎 Search Terms

reverse mapped constraint inference candidates

🕗 Version & Regression Information
  • This is the behavior in every version I tried
⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.3.0-dev.20231028#code/JYOwLgpgTgZghgYwgAgApynAthSVgBeEAJgPIBGAVhAmMgN4BQyyYAngA4QBcyAzmHwgA5gG5myDhmx8A-LwBKNAPZRiAHgFDhAGmQBXEAGsQygO4gAfOIC+jRsRoAbDChiHawZSH659HdQkAFQBhb0gADzAdYIBxfQxiPmQIKIgQJOQlBFUNLVBdNGkcPEISCmpaAG0AIilMLD4agF1kAB8DDIgYUBJLGMsACgB9XiYWdi4+MYkWHPBUsF5Q8MXxFht15GEEtWmGWeQqgGlkUGQjCDZlGGQg+MS+Zt5B+cilu7CFqL16mWWHnsTs0AJTIAC8lmQADdlMBiFtNowbCCAbskuJGPMBMgoBA+PonHRwb4wP5BuNWJx8TMWHNVlFaXT6YYPgBGAAMHJizJsPOQfIkO0eTLmAAsaEYAGLKZQvYZ6ejIGCygVjZWy3j5EQCsGQjXKCHgkk1FXKGr8lhwJxmOBsPhBKD6HjIEZ6qGCZ38wUozF4glE8QAeiDyAAerJ7IwgA

💻 Code
interface ParameterizedObject {
  type: string;
  params?: Record<string, unknown>;
}

declare function setup<
  TContext,
  TGuards extends Record<string, ParameterizedObject["params"] | undefined>,
>(_: {
  types: {
    context: TContext;
  };
  guards: {
    [K in keyof TGuards]: (context: TContext, params: TGuards[K]) => void;
  };
}): TGuards;

const result = setup({
  types: {
    context: {
      count: 100,
    },
  },
  guards: {
    checkFoo: (_, { foo }: { foo: string }) => foo === "foo",
    alwaysTrue: (_) => true,
  },
});

result;
// ^?
🙁 Actual behavior
Type '(_: { count: number; }, { foo }: { foo: string; }) => boolean' is not assignable to type '(context: { count: number; }, params: Record<string, unknown> | undefined) => void'.
  Types of parameters '__1' and 'params' are incompatible.
    Type 'Record<string, unknown> | undefined' is not assignable to type '{ foo: string; }'.
      Type 'undefined' is not assignable to type '{ foo: string; }'.(2322)
🙂 Expected behavior

I'd expect the inference to succeed here

Additional information about the issue

TGuards is inferred as { checkFoo: { foo: string; }; alwaysTrue: unknown; } and thus rejected by the constraint check in getInferredType. alwaysTrue is inferred as unknown because inferReverseMappedType has such a return:

return getTypeFromInference(inference) || unknownType

And getTypeFromInference doesn't attempt to read the type parameter's constraint at all. It simply handles .candidates and .contraCandidates and that's it.

主要语言
Go
星标
111k
派生
14.4k
平均合并
1 天 19 小时
30 天内合并 PR
117

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

microsoft/TypeScript 的其他 Issue

查看 microsoft/TypeScript 的全部 Issue

相似的 Issue

更多 Go Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。