【问题标题】:Typescript - How to get keys behind specific values from an objectTypescript - 如何从对象中获取特定值后面的键
【发布时间】:2022-07-05 22:36:44
【问题描述】:

我有一个超级简单的用例。我想要一个函数pluckOnlyStringValues,在该函数上传递一个对象obj 和一个key,我想确保我只能传递值为string 的键。这样pluckOnlyStringValues 总是返回string

为了这个目标,我正在尝试实现一个类型帮助器 PickKeysByValue,但它似乎不起作用......

type PickKeysByValue<T extends object, ValueTypes> = {
  [K in keyof T]-?: T[K] extends ValueTypes ? K : never;
}[keyof T];

// Working
type GetKeysWithStringValues = PickKeysByValue<
  { a: string; b?: string; c: number | undefined; d: () => 4 },
  string
>;
// Working
type GetStringValues = { a: string; b?: string; c: number | undefined; d: () => 4 }[GetKeysWithStringValues]

// Not working
const pluckOnlyStringValues = <O extends { a: string }>(
  obj: O,
  key: PickKeysByValue<O, string>,
): string => {
  return obj[key];
};

【问题讨论】:

  • 为什么要将O 限制为{ a: string }?您应该将其替换为Record&lt;string, any&gt;Record&lt;string, any&gt; &amp; { a: string },以表明obj 可以使用string 进行索引。

标签: typescript typescript-generics typescript-utility


【解决方案1】:

pluckOnlyStringValues 实现中,O 是未知的,所以PickKeysByValue&lt;O, string&gt; 也是未知的。 TypeScript 不够聪明,无法确定 obj[key] 始终是 string 类型

您可以添加一个function overload,它与您当前的声明和实现兼容。

function pluckOnlyStringValues<O extends { a: string }>(
  obj: O,
  key: PickKeysByValue<O, string>,
): string
function pluckOnlyStringValues(
  obj: Record<string, string>,
  key: string,
): string {
  return obj[key];
};

TypeScript playground

【讨论】:

    【解决方案2】:

    根据你的描述,..

    您可以使用辅助类型StringKeys 来执行此操作,这将只返回字符串类型的键。

    const test = {
      aNumber: 12,
      aString: 'ABC'
    } as const;
    
    type StringKeys<T extends object> = {
      [K in keyof T]: T[K] extends string ? K : never
    }[keyof T];
    
    function pluckString<T extends object>(obj:T, key:StringKeys<T>) {
    }
    
    pluckString(test, 'aString')  //ok
    pluckString(test, 'aNumber'); //error
    

    Playground

    【讨论】:

      猜你喜欢
      • 2022-01-21
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      • 1970-01-01
      • 2017-02-15
      相关资源
      最近更新 更多