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

TypeScript type for object whose values match its keys

是否可以为键值是文字键名本身的对象定义 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"].

如果我没理解错的话,这就是你想要的:

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"];

您正在查找的内容目前在 TypeScript 中不可用。如果您有一些有限的字符串文字键联合,它会起作用,但不适用于所有 string。在 microsoft/TypeScript#22509 asking for this exact thing (called Thing instead of SpecialGenericType in the description), but there hasn't been any movement. The chief language architect said

有一个开放的建议

This really is a request to add compiler support for ECMAScript proxy objects, i.e. compiler knowledge of the relationship between property access operations and the get and set proxy methods. It is simply not possible to model that with our current type system features (because nothing allows you to capture the literal type corresponding to the property name in a property access).

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