如何使用具有静态和动态类型属性的类型

How to use a type with static and dynamic typed properties

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

类型定义如下:

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']

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

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

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

简短的回答是 FooBarBar 不兼容,因为 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)

如果您想将 Bar 分配给 Foobar,您必须提供相应的签名,该签名基本上等于您的 FooBar 类型。 将 FooBar 分配给 Bar 应该总是可行的