【发布时间】:2020-04-22 18:43:52
【问题描述】:
我正在尝试将一个项目存储在一个对象中,其中对象键是类型的鉴别器。
请参阅下面的编辑。
这是一个简单的例子:
type Foo = {
id: 'foo'
}
type Bar = {
id: 'bar'
}
type Container = {
foo: Foo
bar: Bar
};
const container: Container = {
foo: { id: 'foo' },
bar: { id: 'bar' },
};
function storeValue(value: Foo | Bar) {
container[value.id] = value; // <= Error happens here. See below.
}
这是我得到的完整错误
TS2322: Type 'Foo | Bar' is not assignable to type 'Foo & Bar'.
Type 'Foo' is not assignable to type 'Foo & Bar'.
Type 'Foo' is not assignable to type 'Bar'.
Types of property 'id' are incompatible.
Type '"foo"' is not assignable to type '"bar"'.
我尝试过这样的事情:
type Container = {
[key in (Foo|Bar)['id']]: FooBar | undefined
}
有了这个,错误就消失了......但是它允许这样的事情(在 container.foo 中分配一个 Bar):
function storeValue(value: Foo | Bar) {
container.foo = value; // OK... but it shouldn't be.
}
有没有办法从key 推断类型?
type Container = {
[key in (Foo|Bar)['id']]: ??? | undefined // <= Here, infer the type based on the `key`
}
我阅读了文档、FAQ、尝试了很多东西、阅读了很多 SO 帖子、GitHub 问题......我没有找到任何东西。
编辑:其他示例(仍然简化,但更接近我的用例。仅供参考,我使用的是 Twilio Video)
type DataPublication = {
kind: 'data';
// other props
}
type AudioPublication = {
kind: 'audio';
// other props
}
type VideoPublication = {
kind: 'video';
// other props
}
type Publication = DataPublication | AudioPublication | VideoPublication;
class Whatever {
publications: {
data: DataPublication | undefined
audio: AudioPublication | undefined
video: VideoPublication | undefined
} = {
data: undefined,
audio: undefined,
video: undefined
}
handlePublishedWorking(publication: Publication) {
switch (publication.kind) {
case 'data':
this.publications.data = publication; // publication is narrowed to DataPublication
break;
case 'audio':
this.publications.audio = publication; // publication is narrowed to AudioPublication
break;
case 'video':
this.publications.video = publication; // publication is narrowed to VideoPublication
break;
}
}
handlePublishedNotWorking(publication: Publication) {
this.publications[publication.kind] = publication;
}
}
【问题讨论】:
-
你的对象键,例如
foo不是类型鉴别器Foo。听起来您正在寻找在编译时检查 typescript 类型以更改运行时属性.. -
你可以在
Foo和Bar中添加一个kind: string属性来区分吗?你的类型是相同的。了解您的用例可能也很有用,因为可能有更好的方法 -
我添加了我的用例。
-
这没有任何意义。您的代码示例甚至无法编译。请使用最小可验证完整示例编辑您的问题。
-
不必粗鲁。我更新了我的问题以修复代码示例。抱歉弄错了。
标签: typescript