对于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'; // okayAnother 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 : neverThat 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!
更多推荐
发布评论