Typescript 从具有指定类型的泛型函数中的条件类型提取所有属性的最佳方法
我有一种提取类型,叫做Typescript 从具有指定类型的泛型函数中的条件类型提取所有属性的最佳方法,typescript,templates,generics,metaprogramming,typescript-generics,Typescript,Templates,Generics,Metaprogramming,Typescript Generics,我有一种提取类型,叫做 type ExtractProps<T, K> = { [C in keyof T]:T[C] extends K ? K: never } 从不在typescript中被视为底部类型,因此它不应包含任何值。这意味着编译器应该忽略never类型的props,因为它不包含值。然而,事实并非如此,这意味着这必须是预期的特性。从具有指定类型的对象提取属性有哪些解决方法 新更新 所以我在网上查了一下,找到了一个解决办法 type ExtractProps<T,
type ExtractProps<T, K> = { [C in keyof T]:T[C] extends K ? K: never }
从不
在typescript中被视为底部类型,因此它不应包含任何值。这意味着编译器应该忽略never
类型的props,因为它不包含值。然而,事实并非如此,这意味着这必须是预期的特性。从具有指定类型的对象提取属性有哪些解决方法
新更新
所以我在网上查了一下,找到了一个解决办法
type ExtractProps<T, TProps extends T[keyof T]> = Pick<T, ExtractPropsKey<T, TProps>>;
type ExtractPropsKey<T, TProps extends T[keyof T]> = {
[P in keyof T]: T[P] extends TProps ? P : never;
}[keyof T];
type ExtractProps=Pick;
类型ExtractPropsKey={
[P in keyof T]:T[P]扩展TProps?P:从不;
}[keyof T];
这些类型可以工作,但是我的运行时函数不接受类FormField
,因为它不扩展t[keyof t]
,即使FormField可能是FormRelation
的类型
是否有任何可能的方法将所有泛型条件类型提取到单个联合类型中
短语“泛型条件类型”让我害怕。如果条件类型依赖于未指定的泛型类型参数,如在run()
的实现中,则TypeScript编译器无法对其进行太多类型分析。它主要推迟分析,无法确认是否有任何值可分配给它
如果指定了类型参数,编译器可以完全计算条件类型,并理解,例如,ExtractProps
是{b:number}
。但是ExtractProps
对于未指定的泛型T
是一个谜。编译器不理解您可以将该类型的任何属性分配给number
类型的变量
我倾向于认为泛型条件类型只对那些可以指定泛型类型参数的人有用。对于像run()
这样的通用函数,这意味着它只对该函数的调用者有用。实现应该避免这种类型。让函数实现使用不同于调用方的类型签名的一种方法是将其设置为函数,如下所示:
function run<T>(props: FormRelation<T>): void;
function run(props: Record<string, FormField | FormFieldGroup>) {
const fields = extract(props, [FormField]);
}
这会产生一些已知的属性值V
。是的,它会忘记对象的特定键
,但在run()
的实现中,您无论如何都不可能知道这些键,因此让extract()
尝试维护这些键是没有意义的。run()
的实现应该关心的唯一一件事是extract(props,[FormField])
应该是属性都是FormField
的东西,这就是extract()
的功能
那就是我建议去的地方。我将在这里提及示例代码中的其他问题,尽管它们不适用于您的完整代码库:
- 您的
和FormField
类在结构上是相同的,因为它们都是空的。假设您希望编译器看到FormFieldGroup
和FormField
类型不同,那么应该为它们提供不同的结构FormFieldGroup
- 函数签名
函数运行(props:FormRelation):void代码>不是特别有用。通常,如果编译器可以推断类型参数,而不是要求用户手动指定类型参数,那么泛型函数对用户最为友好。但是在这个签名中,无法从
道具的类型推断
T
有损;FormRelation
的类型必须看起来像props
之类,并且没有办法将其反向工程为类似{a:FormField,b:FormFieldGroup,c:FormField}
的类型。因此,获得相关的{a:string,b:number[],c:boolean}
和T
的唯一方法是调用方手动指定props
。为什么呢?返回类型为T
,它不依赖于void
。因此,调用者甚至没有动力确保t
被正确使用。签名T
run(props:T):无效从调用方的角度来看,code>可能更好
好的,希望这能给你一些指导。祝你好运
因此,我刚刚求助于重载提取函数以接受预期的返回类型
declare function extract<T>(object: {[x: string]: any}, propTypes: {new(...values: any): any}): T
declare函数extract(object:{[x:string]:any},propTypes:{new(…value:any):any}):T
我很确定,如果没有指定泛型,编译器就无法提取特定的条件类型。我仍然要保留前面的泛型类型,因为它在没有条件类型和指定类型参数和未指定类型参数的任何类型上都可以很好地工作
这不是一个完美的解决方案,因此,如果有人有更好的解决方案,请随意将其放下。您应该发布一个完整的示例,最好是完整的示例。。否则这就太模糊了。我刚刚添加了更多关于我试图从中提取的类型和参数类型的详细信息。好的,但问题是是否有办法将所有可能的条件类型提取到单个联合类型中。对不起;我的回答解决了问题“我的运行时函数不接受类
FormField
,因为它不扩展t[keyof t]
,即使FormField
是formrelationprops的一种可能类型。
”我恐怕不明白“将所有泛型条件类型提取到单个联合类型”是什么意思,确切地也许您可以更新您的示例,以明确显示您试图转换为什么?我认为从FormRelation
到Record
的转变可能是你的正确方向;如果没有,我需要更多的细节。祝你好运!
function run<T>(props: FormRelation<T>): void;
function run(props: Record<string, FormField | FormFieldGroup>) {
const fields = extract(props, [FormField]);
}
declare function extract<V>(
object: object,
propsTypes: { new(...value: any): V }[]
): Record<string, V>
declare function extract<T>(object: {[x: string]: any}, propTypes: {new(...values: any): any}): T