microsoft / microsoft/TypeScript
Index type distributes over intersections too eagerly
未关闭
还没有人认领这个 Issue。
Domain: Indexed Access Types
Help Wanted
Possible Improvement
- 主要语言
- Go
- 星标
- 111k
- 派生
- 14.3k
- 平均合并
- 2 天 4 小时
- 30 天内合并 PR
- 132
描述
🔎 Search Terms
index keyof indexed access deferred deferral instantiation
🕗 Version & Regression Information
- This is the behavior in every version I tried
⏯ Playground Link
💻 Code
type Values<T> = T[keyof T];
// transforms from "keyed object map" to a union
type ExtractEventsFromPayloadMap<T> = Values<{
[K in keyof T]: T[K] & { type: K };
}>;
type EnqueueObject<TEmittedEvent extends { type: PropertyKey }> = {
// creates proxy methods
emit: {
[K in TEmittedEvent["type"]]: (
payload: Omit<TEmittedEvent & { type: K }, "type">,
) => void;
};
};
type Exec<TEmitted extends { type: PropertyKey }> = (
enq: EnqueueObject<TEmitted>,
) => void;
declare function createStore<TEmitted>(definition: {
emits: {
[K in keyof TEmitted]: (payload: TEmitted[K]) => void;
};
exec: Exec<ExtractEventsFromPayloadMap<TEmitted>>;
}): any;
createStore({
emits: {
increased: (_: { upBy: number }) => {},
decreased: (_: { downBy: number }) => {},
},
exec: (enq) => {
enq.emit.increased({
upBy: "bazinga", // this should error!
});
const fn = enq.emit.increased;
// ^?
// this is just a copy of what is displayed as `enq.emit.increased`'s type
const exactSameTypeAsAbove: (
payload: Omit<
{ upBy: number } & { type: "increased" } & { type: "increased" },
"type"
>,
) => void = () => {};
exactSameTypeAsAbove({
upBy: "bazinga", // this one errors correctly
});
},
});
🙁 Actual behavior
There is no error on the annotated call
🙂 Expected behavior
It should error
Additional information about the issue
keyof (T & { type: K })gets normalized tokeyof T & "type"- that passed through
Exclude<X, "type">(withinOmit) is left asExclude<keyof T, "type">. - then
Tgets instantiated withExtractEventsFromPayloadMap<{ increased: { upBy: number; }; decreased: { downBy: number; }; } - but now
keyof ...returns only shared keys of this union - the only shared key is
typeso thisExcludegets computed asnever(Exclude<"type", "type">) - and the final parameter type of
enq.emit.increasedgets computed as just{}(from{ [K in never]: ... })
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
从链接的 TypeScript Playground 复现开始,跟踪 indexed access、keyof、intersections 和 Omit 的 checker 路径。将带注解的 callback 调用与等价的显式函数类型进行比较。完成的标准是:推断出的 enq.emit.increased 调用会拒绝将字符串传给 upBy,并且有一个覆盖所报告案例的回归测试。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- typescript
- 领域
- compilers
- Issue 类型
- 缺陷
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 停滞
- 描述清晰度
- 基本清楚
- 新手友好度
- 42/100