typescript - 计算值可索引的对象中键名的联合类型

标签 typescript

我想编写一个 indexByProp 函数,它将索引 Prop 的选择限制为可索引值(字符串、数字、符号)。

本期是 https://github.com/microsoft/TypeScript/issues/33521 的延续。到目前为止,我尝试构建此功能可以在 TS Playground link 中找到。 .

我期望的期望结果是,例如:

indexByProp('bar', [{ // should be ok
  bar: 1, 
  foo: '2', 
  qux: () => {}
}])

indexByProp('qux', [{ // should be type error
  bar: 1, 
  foo: '2', 
  qux: () => {}
}])

最佳答案

您正在寻找这样的东西:

type KeysMatching<T, V> = NonNullable<
  { [K in keyof T]: T[K] extends V ? K : never }[keyof T]
>;

哪里KeysMatching<T, V>给你 T 的 key 其属性可分配给 V 。它looks up mapped 的属性值, conditional键入以执行此操作。展示其工作原理的示例:

interface Foo {
  a?: string;
  b: number;
}

// give me all the keys of Foo whose properties are assignable to 
// string | undefined... expect to get "a" back
type Example = KeysMatching<Foo, string | undefined>;

评估如下:

type Example2 = NonNullable<
  {
    a?: Foo["a"] extends string | undefined ? "a" : never;
    b: Foo["b"] extends string | undefined ? "b" : never;
  }["a" | "b"]
>;

type Example3 = NonNullable<
  {
    a?: string | undefined extends string | undefined ? "a" : never;
    b: number extends string ? "b" : never;
  }["a" | "b"]
>;

type Example4 = NonNullable<{ a?: "a"; b: never }["a" | "b"]>;

type Example5 = NonNullable<"a" | undefined | never>;

type Example6 = NonNullable<"a" | undefined>;

type Example7 = "a";

这给出了"a"正如预期的那样。


然后,IndexableKeys只是:

type IndexableKeys<T> = KeysMatching<T, keyof any>;

还有你的indexByProp()函数看起来像:

const indexByProp = <X extends Indexable>(
  propName: IndexableKeys<X>,
  xs: X[]
): Indexable<X> => {
  const seed: Indexable<X> = {};
  return xs.reduce((index, x) => {
    const address = x[propName];
    index[address as keyof typeof index] = x; // need assertion
    return index;
  }, seed);
};

您的测试行为符合预期:

indexByProp("bar", [
  {
    bar: 1,
    foo: "2",
    qux: () => {}
  }
]); // okay

indexByProp("qux", [
  //        ~~~~~  error!
  // Argument of type '"qux"' is not assignable to parameter of type '"bar" | "foo"'.
  {
    // should be type error
    bar: 1,
    foo: "2",
    qux: () => {}
  }
]);

希望有帮助;祝你好运!

Link to code

关于typescript - 计算值可索引的对象中键名的联合类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58030413/

相关文章:

javascript - 按键过滤 map

visual-studio - 使用 Visual Studio 2012 express 进行 TypeScript、node.js 开发

javascript - 如何从 Angular5 组件 mydaterangepicker 中删除 "position: absolute"?

reactjs - 使用 Webpack 5 typescript 构建的 React 在浏览器中编译时出现问题。 @tailwind 指令不工作 postcss-loader postcss.config.js Emit skipped

node.js - 如何创建一个自定义管道来接收对象作为 Angular 4 中的过滤器

javascript - Angular 2在字符串化为JSON时如何保持表单输入的正确类型

json - 将 Typescript 类转换为字符串,使用 getter 和 setter 而不是私有(private)变量

typescript - this.$refs.Form.validate 不是我的 vue 组件中的函数

reactjs - Vite React TypeScript monorepo 热模块重新加载(HMR)不起作用

typescript - 在 TypeScript 中展平数组