TypeScript:具有除一个以外的任何键的对象

标签 typescript

我只想要一个这样的类型:

type ObjectWithAnyKey = { [key: string]: string };

允许除 foo 之外的所有键 key 。

怎么做?

最佳答案

我认为在这种情况下,您可以使用以下定义:

type ObjectWithAnyKeyExceptFoo = {
  [key: string]: string
} & { foo?: never };

型号{foo?: never}有一个名为 foo 的可选属性,其类型为 never (实际上与可选属性的 undefined 相同)。因此,如果您有一个名为 foo 的属性,它不能有一个定义的值。实际上从 undefined & stringnever ,你不能有 foo属性(property)。让我们确保它有效:
function acceptAnyKeyAcceptFoo(obj: ObjectWithAnyKeyExceptFoo) { }

acceptAnyKeyAcceptFoo({}); // okay
acceptAnyKeyAcceptFoo({ a: "123" }); // okay
acceptAnyKeyAcceptFoo({ a: "123", foo: "oops" }); // error!
//  ----------------------------> ~~~
// Type 'string' is not assignable to type 'undefined'.
acceptAnyKeyAcceptFoo({ a: "123", foo: undefined }); // error!
//  ----------------> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Type 'undefined' is not assignable to type 'string'.

看起来挺好的。

更多技术内容如下:

请注意,使用 intersection ( & ) 这里有点奇怪,甚至可能有点作弊。与 index signature , 手动指定属性,如 foo还需要具有可分配给其索引签名属性类型的值。以下不起作用,因为它违反了:
type BadDefn = {
  [key: string]: string;
  foo?: never; // error!
//~~~ <-- undefined is not assignable to string
}

foo可能是 undefined ,但是 string不是,编译器不高兴。没关系,来自索引签名的大多数值实际上是 undefined而不是 string (例如, const obj: ObjectWithAnyKeyExceptFoo = {a: "123"} 有一个 a 类型的属性 string ,但是如果你访问它的 b 属性呢?你会在运行时得到 undefined,但编译器会说 string)。 But that's the way index signatures are , 我猜。

交集定义与上面不允许的类型本质上是一样的,只是它避开了编译器错误。故意这样做会违反索引签名(请参阅 this question )通常会出现问题,但我们实际上并不想使用该违反属性。我们不要foo属性,因为编译器看到 foo属性为 string & undefined , 即 never ,它实际上更适合这个用例。

可以制作像这样的非违规单一类型:
type OkayDefnButPossiblyUndefined = {
  [key: string]: string | undefined;
  foo?: never;
}

如果你想代表那个obj.b,这个其实是合理的。是 undefined而不是 string ,但如果您喜欢当前的索引签名行为,则可能不是最合适的。还有这个:
type AlsoOkayButRequiresFoo = {
  [key: string]: string;
  foo: never;
}

更糟的是,因为 foo成为必需的属性,实际上很难初始化这种类型的东西。

结束技术性的东西

好的,希望有帮助。祝你好运!

Link to code

关于TypeScript:具有除一个以外的任何键的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58594051/

相关文章:

javascript - 如何使用 Aurelia 通过单击内部 anchor 链接来保持在同一页面上?

typescript - TypeORM @OneToMany 在调用时似乎不会尝试执行

typescript - 如何正确覆盖 typescript 中的方法?

javascript - 使用 Angular 2 接口(interface)

typescript - 应该如何使用 TypeScript 编译器 API 的 'module resolution cache'?

mysql - 我如何将 typescript 回调转换为 promise

reactjs - TypeScript Rest Props - 允许任何 Prop 或告诉组件它们将成为哪些 Prop

javascript - Phaser3 ascii 图形

Angular2 RC5 : Can't bind to 'Property X' since it isn't a known property of 'Child Component'

node.js - Angular2 + TypeScript + moment.js => 语言环境并不全部存在(只是 'en' )