值与其键匹配的对象的 TypeScript 类型

Posted

技术标签:

【中文标题】值与其键匹配的对象的 TypeScript 类型【英文标题】:TypeScript type for object whose values match its keys 【发布时间】:2020-10-12 20:23:22 【问题描述】:

是否可以为键值是文字键名本身的对象定义 TypeScript 类型?例如:

declare const $: SpecialGenericType

$.prop // typed as the literal value "prop"

const values = [
  $.a,
  $.b,
  $.c
] as const

// values has the type (and value) ["a", "b", "c"]

$ 对象可以使用代理来实现,但我不确定如何实现SpecialGenericType。该类型需要允许任何字符串作为键,但需要将值键入为其键名的字符串文字(因此Record<string, string> 在这种情况下不起作用)。例如,上面的values 将具有元组类型["a", "b", "c"]

【问题讨论】:

【参考方案1】:

您正在寻找的内容目前在 TypeScript 中是不可能的。如果您有一些有限的字符串文字键联合,它会起作用,但不适用于所有string。在microsoft/TypeScript#22509 有一个公开的建议要求这个确切的东西(在描述中称为Thing 而不是SpecialGenericType),但没有任何动静。首席语言架构师said

这确实是一个为 ECMAScript 代理对象添加编译器支持的请求,即编译器了解属性访问操作与 getset 代理方法之间的关系。使用我们当前的类型系统功能根本不可能对其进行建模(因为没有任何东西可以让您捕获与属性访问中的属性名称对应的文字类型)。

您可能想解决该问题并给它一个 ? 或描述您认为您的用例具有吸引力的原因,但我怀疑它是否会很快实施。哦,好吧,至少这个问题有一个明确的答案,即使它是“否”。祝你好运!

【讨论】:

【参考方案2】:

如果我理解正确,这就是你想要的:

type SpecialGenericType<T extends object> = 
  [K in keyof T]: K
;

function proxify<T extends object>(source: T) 
  const proxy = new Proxy(source, 
    get: (_, property) => 
      return property
    
  );

  return proxy as SpecialGenericType<T>;


const $ = proxify(
  prop: ,
  a: 'some',
  b: 'random',
  c: 'values',
 as const)

$.prop // typed as the literal value "prop"

const values = [
  $.a,
  $.b,
  $.c
] as const

// values has the type (and value) ["a", "b", "c"];

【讨论】:

差不多,但是属性键是提前未知的,它需要允许指定任何键。对于运行时等效项,我正在寻找一种模拟 new Proxy(, get: (_, prop) =&gt; prop) 的类型 如果将其包装在一个函数中会有所帮助,它可能是:function ($) // $ is the magic object within here 更新了我的答案。这有帮助吗? 不幸的是,仍然没有 - 在您对 proxify 的调用中,您传入了一个带有所需键的对象,然后将值转换为键名。我的问题是它需要使用 all possible 键名,并且这些键名事先不知道。例如,$ 类型存在于库中,该库的使用者需要能够 $.anything 并且类型仍然有效,而没有列出所有可能键的对象。

以上是关于值与其键匹配的对象的 TypeScript 类型的主要内容,如果未能解决你的问题,请参考以下文章

Typescript:如何声明一种值等于对象键的数组类型?

打字稿 |从对象 T 中提取具有类型 K 值的所有键名

TypeScript 中每个键的泛型映射对象类型

如何获取与 Typescript 中的接口匹配的对象的所有属性? [复制]

打字稿如何定义对象,其中键的值取决于另一个键

TypeScript 映射类型键/值