0

我正在尝试使用具有一种类型的所有属性的类型,但也允许添加另一种类型的动态属性(类似于这个问题)。

类型定义如下:

type Foo = string | string[]
type Bar = { n: number, str?: string }

// A dictionary which only allows Foo values
type FooDict = { [key: string]: Foo | undefined }

// Has all static properties of Bar plus some dynamic Foo properties
type FooBar = FooDict & Bar

我期待像这样使用它们:

const bar: Bar = { n: 1 }
const fooBar: FooBar = bar
const n: number = fooBar.n
const str: string | undefined = fooBar.str
const foo: Foo | undefined = fooBar['someRandomKey']

问题是第二行给出了编译错误:“类型'Bar'不可分配给类型'FooBar'。类型'Bar'不可分配给类型'FooDict'。属性'n'与索引签名不兼容。类型' number' 不可分配给类型 'Foo | undefined'。TS2322"

我看不出它无法工作的任何原因。

  • Bar和的所有键FooDict都是字符串,所以没有不匹配。
  • 如果使用 的键Bar,我们可以使用 Bar 对应的静态属性。
  • 否则,我们可以使用 from 的类型FooDict,它是Foo(当属性存在时)或undefined(当使用没有值的键时)。

如链接问题中所述,如果将动态属性键入为any. 但是由于我只需要将 Foo 实例设置为动态属性,因此我想使用类型系统强制执行它。这可能吗?

4

1 回答 1

0

简短的回答是,FooBar并且Bar不兼容,因为FooBar承诺基于字符串的索引签名而Bar没有。(基本上这就是错误消息所说的)

const fooBar: FooBar = {...}
const bar: Bar = fooBar;

// this will work since foobar has a string index signature
fooBar['someRandomKey'] // undefined | Foo

// this will give a compilation error since there is no string based index signature
bar['someRandomKey'] // NOTE: it will work at runtime though (which is why it is so confusing)

如果你想给BarFoobar提供一个基本上等于你的FooBar类型的相应签名。分配FooBarBar应该总是可能的

于 2021-12-15T10:58:05.593 回答