microsoft / microsoft/TypeScript

Branded literal type widened in unexpected way

未关闭
#61,093 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

Bug Domain: Intersection Help Wanted
主要语言
Go
星标
111k
派生
14.3k
平均合并
2 天 4 小时
30 天内合并 PR
132

描述

### 🔎 Search Terms

literal intersection branded string

### 🕗 Version & Regression Information

- This is the behavior in every version I tried, and I reviewed the FAQ for entries about branded strings/literal intersections.

### ⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.7.3#code/CYUwxgNghgTiAEYD2A7AzgF3hgngBxAGkQcAueAVxQEsBHChNHAWwCMkIBuAKG9wPgAVfCACSAEQA8wgQF5KKANYokAdxQAaeBPggAHhhApgaeJhjUUAc3jzzlqwD5b28fABk8AN7wA2vyISAF0AfnIZBABfHm4AMyowDGpUbBEJaREtHX1DY1N7a0cACmpgcgkASnC0qQis8Wcvbnh4OAwKGBR4Up5I3gD4YhwAeVjpbIMjEyEa53lBCdzpiPSoFBwtS1iQGFdnENd4chQQADcdmIGI0fG3HKnTFYaXBbvJvJmCdK2dz5B9v5HeAnc4wS4ieAABRgSFOpRAaEkkN072WsxcPjgUGAqAgOD8gm6XSGN0hjiC1QIpOc0V4AHo6fAALQssAUDAspm8SyGGCxKBgBAAMSQSG8zRa8FioqKVXgpyQPW4fW4yHQWBFYvkAQkRQARJq9RUzFAkmhYtQEX90prHDwGZL4AA9EK8NWYeAAIVg5GhsPhiICSFi8FtGIlLV8mop4sdjulSFl3j6jr60SAA

### 💻 Code

```ts
declare const typeKey: unique symbol;

type TypeID = ID & { [typeKey]?: Type };

function typeID(id: ID): TypeID {
return id;
}

type KeyOf = TID extends TypeID ? ID : never;

type TypeOf = TID extends TypeID ? Type : never;

type Provides

= { readonly [T in KeyOf

]: TypeOf

};

// ---cut---

interface Foo {
foo(): void;
}

const Foo = typeID("Foo") satisfies TypeID;
// ^? const Foo: TypeID

const Bar: Provides = {
[Foo]: {
foo() {}
}
};
```

### 🙁 Actual behavior

Fails to compile with error:

```
Property 'Foo' is missing in type '{ [x: string]: { foo(): void; }; }' but required in type 'Provides>'.
```

### 🙂 Expected behavior

I'd expect it to compile. Rather than widening the literal type to `string`, I'd expect it to discard the `{ [typeKey]?: Type }` part, since that's pretty much bogus at runtime anyway.

However, it should also not lose the type information for the generic types. For instance, if I change the declaration to...

```ts
type TypeID = ID;
```

...then it does compile, but so does this...

```ts
const Bar: Provides = {
[Foo]: {
// No error about missing member `foo` here!
}
};
```

### Additional information about the issue

Possibly related to https://github.com/microsoft/TypeScript/issues/43852#issuecomment-1671115898

贡献指南

打开贡献指南

从这里开始

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

调研方向

从 TypeScript Playground 中的复现开始,并将 branded literal 的行为与 issue #43852 中的相关讨论进行比较。跟踪针对 `TypeID`、`KeyOf`、`TypeOf` 和 `Provides` 定义的类型检查路径;完成的标准是示例能够编译,同时在适当情况下仍报告缺少 `foo` 成员。

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

评估

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

把新 issue 发到你的邮箱

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