过滤对象的键,使得只返回指向数组的键(而不是'keyof'的所有键)(Filter keys of object such that only keys pointing to a

编程入门 行业动态 更新时间:2024-10-07 14:31:47
过滤对象的键,使得只返回指向数组的键(而不是'keyof'的所有键)(Filter keys of object such that only keys pointing to array are returned (instead of all keys by 'keyof'))

对于student.ts

type Student = { name: string, marks: string[], subjects: string[] }

如何获取ArrayKey<Student> ,使其仅返回指向任何数组的键,此处应指向'marks'|'subjects'

我的尝试

type ArrayKey<T, Key extends keyof T = keyof T> = T[Key] extends any[] ? Key : never; let c: ArrayKey<Student> = 'marks';

但它抛出错误[ts] Type '"marks"' is not assignable to type 'never'

For student.ts

type Student = { name: string, marks: string[], subjects: string[] }

How to get ArrayKey<Student> such that it return only keys which points to any array, here it should point to 'marks'|'subjects'

My try

type ArrayKey<T, Key extends keyof T = keyof T> = T[Key] extends any[] ? Key : never; let c: ArrayKey<Student> = 'marks';

but it throws error [ts] Type '"marks"' is not assignable to type 'never'

最满意答案

你很接近,但你的代码要求开发人员指定Key ,这是你想要输出的。 您可以使用映射类型迭代T的键,然后使用条件类型来标识具有数组值属性的类型。 喜欢这个:

type ArrayKey<T> = { [Key in keyof T]: T[Key] extends any[] ? Key : never }[keyof T]; type Student = { name: string, marks: string[], subjects: string[] } let c: ArrayKey<Student> = 'marks'; // okay

另一种更接近原始定义的方法是使用分布式条件类型在K的成分上分配条件:

type ArrayKey<T, Key extends keyof T = keyof T> = Key extends any ? T[Key] extends any[] ? Key : never : never

这也可以,但K必须是一个裸类型参数和Key extends any可能令人困惑(分配条件类型有点令人惊讶)并且它滥用K的默认值作为黑客,所以我不推荐它。 不那么hacky但仍然使用分配条件类型:

type ArrayKeyInner<T, Key extends keyof T> = Key extends any ? T[Key] extends any[] ? Key : never : never type ArrayKey<T> = ArrayKeyInner<T, keyof T>

这不会滥用默认参数,这很好。 尽管如此,分布式条件类型的意外因素仍然如此整体,我仍然建议使用映射类型解决方案。


希望有所帮助。 祝你好运!

You're close, but your code requires the developer to specify Key, which is what you're trying to output. You can instead use mapped types to iterate over the keys of T and then use your conditional type to identify the ones with array-valued properties. Like this:

type ArrayKey<T> = { [Key in keyof T]: T[Key] extends any[] ? Key : never }[keyof T]; type Student = { name: string, marks: string[], subjects: string[] } let c: ArrayKey<Student> = 'marks'; // okay

Another way to do it which is closer to your original definition would be to use a distributive conditional type to distribute the conditional over the contituents of K:

type ArrayKey<T, Key extends keyof T = keyof T> = Key extends any ? T[Key] extends any[] ? Key : never : never

That will also work, but K has to be a bare type parameter and Key extends any might be confusing (distributive conditional types are a bit surprising) and it's abusing the default value of K as a hack, so I wouldn't recommend it. Less hacky but still using distributive conditional types:

type ArrayKeyInner<T, Key extends keyof T> = Key extends any ? T[Key] extends any[] ? Key : never : never type ArrayKey<T> = ArrayKeyInner<T, keyof T>

That doesn't abuse a default parameter, which is nice. Still, the distributive conditional type surprise factor still holds so overall I'd still recommend the mapped type solution.


Hope that helps. Good luck!

更多推荐

本文发布于:2023-04-29 09:26:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1335585.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:数组   而不是   对象   keyof   Filter

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!