Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays Typescript:如何创建数组泛型类型,该类型包含具有给定接口的每个实例的对象_Arrays_Typescript_Generics - Fatal编程技术网

Arrays Typescript:如何创建数组泛型类型,该类型包含具有给定接口的每个实例的对象

Arrays Typescript:如何创建数组泛型类型,该类型包含具有给定接口的每个实例的对象,arrays,typescript,generics,Arrays,Typescript,Generics,我有接口 interface Item { location: string; description: string; } interface Field<T extends object> { name: keyof T; label: string; } 和通用字段接口 interface Item { location: string; description: string; } interface Field<T extends obj

我有接口

interface Item {
  location: string;
  description: string;
}
interface Field<T extends object> {
  name: keyof T;
  label: string;
}
和通用字段接口

interface Item {
  location: string;
  description: string;
}
interface Field<T extends object> {
  name: keyof T;
  label: string;
}
正确:

const fields: Every<Field<Item>[]> = [
  { name: 'description', label: 'Description' },
  { name: 'location', label: 'location' },
];
const字段:每=[
{name:'description',label:'description'},
{name:'location',label:'location'},
];

TypeScript没有像这样表示穷举数组的内置功能。您可以尝试编写一个类型,该类型是满足您的条件的所有可能类型中的一个,但是对于中等大小的联合来说,它的伸缩性不好,如果您希望允许重复条目,那么对于小的情况甚至可能不易处理

如果我真的想这样做,我倾向于编写一个帮助函数,尝试从数组中推断字段名,然后使用一个函数,如果这些字段名没有用尽
keyof T
,就会导致编译器错误。这可能很脆弱,也很复杂,但这里有一个可能的实现:

interface FieldNamed<K extends PropertyKey> {
  name: K,
  label: string
}

const exhaustiveFieldArray = <T extends object>() => <K extends keyof T>(
  ...fields: [FieldNamed<K>, ...FieldNamed<K>[]] &
    (keyof T extends K ? unknown : FieldNamed<Exclude<keyof T, K>>[])
): Field<T>[] => fields;

const exhaustiveItemFieldArray = exhaustiveFieldArray<Item>();
我觉得这一切都很好。如果缺少字段,则会出现错误


下面是它的工作原理示意图。返回的函数位于类型参数
K/T
中。
fields
rest参数有两种类型。第一个用于推断传入的内容:

[FieldNamed<K>, ...FieldNamed<K>[]]
此条件类型检查扩展K的键。如果是真的,那么一切都很好,我们返回
unknown
。与
unknown
相交是一个no op(
XYZ&unknown
相当于
XYZ
),因此这不会阻止任何编译。如果它为false,那么我们就有问题了,我们返回
FieldNamed[]
。从联合中删除元素;因此,
Exclude
为我们提供了我们遗漏的那些密钥。所以我们将实际的数组类型与我们遗漏的字段数组相交。这将导致编译器错误,抱怨您遗漏了一些内容。这些错误可能不是最容易理解的,但至少有一些错误


那么,万岁?它能发挥最大的作用,但我不知道对你来说是否值得。相反,您可以考虑将数据结构从一个数组(这是编译器很难检查)改为一个对象,该对象的键与 T(这对编译器来说很容易检查)相同。但是这个答案已经很长了,所以我不打算进一步扩展范围来展示如何实现这样的事情。酷!这足够我用了。我没想到会有这么详细的答案。非常感谢。我们有很多定义的数组。所以我更喜欢创建一些数组类型,而不是将所有代码重写为字典。
& (keyof T extends K ? unknown : FieldNamed<Exclude<keyof T, K>>[])