首页 文章

通用键入动态键和T数组的hashmap

提问于
浏览
0

我尝试在typescript中为hashmap创建一个强类型接口 .

hashmap包含一个带有动态字符串名称的键 . 并且 values 包含Generic类型的数组 .

我试着使用以下界面:

export interface DynamicHashmap<T> {
  [dynamicKey: string]: string;
  values: T[];
}

但它不会编译并继续抱怨:

[ts]类型'T []'的属性'值'不能赋予字符串索引类型'string' .

与此类型对应的生成值的示例,它根据对象属性(此处为 User.group )对值进行分组 . dynamicKey 在此解析为 group .

const user1: User = { id: 'userValue1', group: 'someGroupId' };
const user2: User = { id: 'userValue2', group: 'someGroupId' }; 
const result = {
  group: 'someGroupId',
  values: [
    { id: 'userValue1', group: 'someGroupId' },
    { id: 'userValue2', group: 'someGroupId' }
  ]
}

我猜静态 values 会干扰动态密钥 .

如何实现我们正在寻找的强类型?

2 回答

  • 1

    通常当我听到“动态”时,我试图理解这是否意味着“仅在运行时知道”或“在编译时知道但在不同位置具有不同的值” . 如果它是前者那么你必须使用非常宽的类型(比如你正在谈论的字符串索引的东西)...如果它是后者,那么你有时可以使用泛型来表达更窄的类型 . 例如,在您的情况下:

    type DynamicHashMap<T, K extends keyof T> = Pick<T, K> & {values: T[]};
    

    要么

    type DynamicHashMap<T, K extends keyof T> = { 
      [P in K | 'values']: P extends K ? T[K] : T[] 
    };
    

    TK 中都是通用的, T 类型的键 . 您可以使用类型推断来实例化 TK ,如下所示:

    // for example
    function makeDynamicHashMap<T, K extends keyof T>(
      key: K, 
      value: T[K], 
      values: T[]
    ): DynamicHashMap<T, K> {
      return { [key]: value, values: values.filter(v => v[key] === value) } as any;
    }
    
    const result = makeDynamicHashMap("group", "someGroupId", [user1, user2]);
    result.group; // string
    result.values; // User[]
    

    所以 result 被推断为类型 DynamicHashMap<User, "group"> . 这有帮助吗?祝好运!

  • 1

    正确的界面是这样的

    export interface DynamicHashmap<T> {
      [key: string]: string | T[];
      values: T[];
    }
    

    这是因为 [key: string] 表示所有键的签名 . 这就是它被称为索引签名的原因 .

    你可能对这种界面不太满意,这就是为什么你应该重新考虑它是另外一样的:

    export interface DynamicHashmap<T> {
      dynamicKey: string;
      dynamicValue: string;
      values: T[];
    }
    

相关问题