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
为我们提供了我们遗漏的那些密钥。所以我们将实际的数组类型与我们遗漏的字段数组相交。这将导致编译器错误,抱怨您遗漏了一些内容。这些错误可能不是最容易理解的,但至少有一些错误
那么,万岁?它能发挥最大的作用,但我不知道对你来说是否值得。相反,您可以考虑将数据结构从一个数组(这是编译器很难检查)改为一个对象,该对象的键与
& (keyof T extends K ? unknown : FieldNamed<Exclude<keyof T, K>>[])