网站搜索

typescript - 我可以在 TypeScript 中将泛型类型用作对象的索引类型吗?


我有一个类似于以下的用例:


type StringKeysOf<T> = [{
  [K in keyof T]-?: T[K] extends string ? K : never
}[keyof T]];

const createDictionary = <T>(key: StringKeysOf<T>) => {

  let dictionary: { [key: string]: T } = {};

  const addToDictionary = (value: T) => {
    dictionary = { ...dictionary, [value[key]]: value }
  }

  return { dictionary, addToDictionary }
}


当尝试将 key 属性用作索引类型时,TypeScript 会报出以下错误信息:Type 'StringKeysOf<T>' cannot be used as an index type.

我认为这是不可能的,因为 T 最终可能包含一个没有任何 string 类型属性的类型(我正在 StringKeysOf 条件类型上进行筛选)。

有人知道有没有办法使这个实现成为可能吗?

答案#1

有几件事你可以做来解决这个问题。首先,请注意 StringKeysOf<T> 是一种 Array 类型。鉴于名称是 key 而不是 keys,我猜你的意思是参数应该是单个值。你需要去掉 []:

type StringKeysOf<T> = {
  [K in keyof T]-?: T[K] extends string ? K : never
}[keyof T];

然后,您需要确保您的 T 具有您期望的形状:

T extends { [K in keyof T]: any }

综合来看:TS Playground

type StringKeysOf<T> = {
  [K in keyof T]-?: T[K] extends string ? K : never
}[keyof T];

const createDictionary = <T extends { [K in keyof T]: any }>(key: StringKeysOf<T>) => {

  let dictionary: { [key: string]: T } = {};

  const addToDictionary = (value: T) => {
    dictionary = { ...dictionary, [value[key]]: value }
  }

  return { dictionary, addToDictionary }
}