【问题标题】:Typescript: How to extract the value types of a const object and use them as keys in a new type?Typescript:如何提取 const 对象的值类型并将它们用作新类型中的键?
【发布时间】:2021-08-23 11:59:41
【问题描述】:

我想获取一个常量对象,比如{key1: 'value1', key2: value2'} as const,并将其值转换为键,并在类型为{value1: number; value2: number} 的新对象中使用它。我想在函数中执行此操作,并且希望正确键入函数。

下面是我尝试开始工作的代码。当我尝试将Partial<Blah> 类型的变量转换为Blah 时,就会发生错误。有人可以解释为什么会发生这种情况,以及是否有办法做我想做的事情?谢谢!

type BaseObject = Record<string, string>;


type ValuesAsKeys<T extends BaseObject> = {
    [K in keyof T as T[K]]: number;
};

function useValuesAsKeys<T extends BaseObject>(arg: T): ValuesAsKeys<T> {
  const x: Partial<ValuesAsKeys<T>> = {};
  for (const value of Object.values(arg) as Array<T[keyof T]>) {
    x[value] = 1;
  }

  // This line doesn't work
  return x as ValuesAsKeys<T>;
}

// Example use case
const obj = {key1: 'value1', key2: 'value2'} as const;
const result = useValuesAsKeys(obj); // Type of result is {value1: number; value2: number}


// Everything below here works
// Only including this because I'm contrasting this code with the code above.

type KeysAsKeys<T extends BaseObject> = {
    [K in keyof T]: number;
};

function useKeysAsKeys<T extends BaseObject>(arg: T): KeysAsKeys<T> {
    const x: Partial<KeysAsKeys<T>> = {};
  for (const value of Object.values(arg) as Array<T[keyof T]>) {
    x[value] = 1;
  }
  return x as KeysAsKeys<T>;
}

【问题讨论】:

    标签: typescript generics types partial


    【解决方案1】:

    我仍然不确定为什么在这种情况下将Partial&lt;Blah&gt; 转换为Blah 不起作用,但是这段代码有效并且对我来说足够安全:

    function useValuesAsKeys<T extends BaseObject>(arg: T): ValuesAsKeys<T> {
      const x = {} as ValuesAsKeys<T>;
      for (const value of Object.values(arg) as Array<T[keyof T]>) {
        x[value] = 1;
      }
      return x;
    }
    

    【讨论】:

      【解决方案2】:

      带有reduce 的显式返回类型几乎总是不起作用,因为initial 的值每次迭代都会改变。

      为了让它工作,最好重载你的函数:

      type BaseObject = Record<string, string>;
      
      
      type ValuesAsKeys<T extends BaseObject> = {
        [K in keyof T as T[K]]: number;
      };
      
      type Values<T> = T[keyof T]
      
      function useValuesAsKeys<T extends BaseObject>(arg: T): ValuesAsKeys<T>
      function useValuesAsKeys<T extends BaseObject>(arg: T) {
        return (Object.values(arg) as Array<Values<T>>).reduce((acc, elem) => ({
          ...acc,
          [elem]: 1
        }), {})
      }
      
      // Example use case
      const obj = { key1: 'value1', key2: 'value2' } as const;
      
      const result = useValuesAsKeys(obj); // Type of result is {value1: number; value2: number}
      result.value1 //ok
      
      

      Playground

      docs

      【讨论】:

      • 在这种情况下,我不喜欢函数重载,因为 typescript 似乎遗漏了明显的错误。例如,使用 string 返回值作为未检测到的过载:function useValuesAsKeys&lt;T extends BaseObject&gt;(arg: T): string
      • @Eric Chen 没问题)
      猜你喜欢
      • 2019-06-28
      • 1970-01-01
      • 2019-05-08
      • 1970-01-01
      • 2019-11-01
      • 2022-09-30
      相关资源
      最近更新 更多