TypeScript type可将对象类型的某些属性动态标记为;“必需”;及;定义为;?
我一直在尝试为下面的函数TypeScript type可将对象类型的某些属性动态标记为;“必需”;及;定义为;?,typescript,generics,type-inference,Typescript,Generics,Type Inference,我一直在尝试为下面的函数useDefaults提供泛型类型: type ValuesOf=T扩展只读任何[]?T[数字]:从不; 需要和定义的类型={ [K中的P]-?:排除; }; 导出类型EnforcedDefaultProps=K从不扩展?P:省略、要求和定义; 导出类型ArrayEnforcedDefaultProps=EnforcedDefaultProps; export const usefaults=( 道具:P |未定义, defaultProps:ArrayEnforcedD
useDefaults
提供泛型类型:
type ValuesOf=T扩展只读任何[]?T[数字]:从不;
需要和定义的类型={
[K中的P]-?:排除;
};
导出类型EnforcedDefaultProps=K从不扩展?P:省略、要求和定义;
导出类型ArrayEnforcedDefaultProps=EnforcedDefaultProps;
export const usefaults=(
道具:P |未定义,
defaultProps:ArrayEnforcedDefaultProps,
强制执行的错误?:只读阵列,
):ArrayEnforcedDefaultProps=>{
const newProps:P={…defaultProps,…props};
如果(enforcedDefaults){//如果用户显式地将undefined传递给prop,则除非密钥位于enforcedDefaults中,否则不会使用默认的prop
强制执行错误
.filter((键)=>newProps[key]==未定义)
.forEach((key)=>newProps[key]=defaultProps[key]);
}
将新道具作为ArrayEnforcedDefaultProps返回;
};
此函数将对两个对象执行简单的基于赋值的操作:一个包含用户提交的选项,另一个包含function developer设置的默认值。然后,它将选择性地对某些属性强制执行非未定义的值(function developer提供),以便useDefaults
的返回对象的类型消除了这些特定属性的值为未定义的可能性。这可以防止函数开发人员不得不使用非空断言,但也不会给函数用户带来负担
所需用途示例:
接口格式选项{
maxLength?:数字,
前缀?:字符串,
后缀?:字符串,
}
常量格式=(值:字符串,_opts?:FormatOpts)=>{
const opts=usefaults(_opts{
前缀:“”,
后缀:“”,
},[“前缀”,“后缀]);
//前缀和后缀此时保证不为“未定义”,但函数的用户不需要在“\u opts”对象中明确指定
const modifiedPrefix=prefix.toUpperCase();//希望避免像prefix!.toUpperCase()这样的事情;
}
//以“前缀”道具为焦点的示例:
格式(“ASDF”);//确定->使用默认值后的前缀:“
格式(“ASDF”,{prefix:“MyPrefix”});//确定->使用默认值后的前缀:“MyPrefix”
格式(“ASDF”,{prefix:undefined});//确定->使用默认值后的前缀:“
格式(“ASDF”,{后缀:“test”});//确定->使用默认值后的前缀:“
我希望使它尽可能动态(尽可能多的类型)
虽然这段代码确实在编译,但不知何故,打字是关闭的。它不是在需要的地方删除带有undefined
s的单个对象类型,而是看起来是每个可能组合的并集。有没有一种更简单的方法来做我想做的事情,或者将这些组合变平
截图的类型与生成的截图完全相同:
我想要的#2类型是
{
只读maxLength?:字符串|未定义;
只读前缀:字符串;
只读后缀:字符串;
}
在阅读@jcalz建议并进行更多实验/简化后,这几乎是动态地生成正确的键入:
类型.ts:
从“ts essentials”导入{StrictOmit};
需要和定义的导出类型={
[K中的P]-?:排除;
};
导出类型MappedObjValue={
[K输入A键和B键]:
A[K]扩展B[K]
从不
:K
};
导出类型OptionalKeys=(MappedObjValue)[keyof T];
导出类型keyworkeysof=(ReadonlyArray)|(keyof P);
导出类型ExtractArrayItem=T扩展只读阵列?U:T;
导出类型EnforcedDefaultProps<
P扩展对象,
K扩展(keyworkeysof
|未定义),
EK=提取阵列项目
>=[EK]扩展[keyof P]?严格省略、要求和定义:P;
导出类型EnforcedDefaultPropsInput<
P扩展对象,
K扩展(keyworkeysof |未定义),
OP扩展对象=拾取,
EK=提取阵列项目
>=[EK]扩展[keyof OP]?强化道具:OP;
useDefaults.ts:
export const usefaults=(
道具:P,
defaultProps:EnforcedDefaultPropsInput,
强制执行错误?:ED,
):EnforcedDefaultProps=>{
const newProps:P={…defaultProps,…props};
如果(enforcedDefaults){//如果用户显式地将undefined传递给prop,则除非密钥位于enforcedDefaults中,否则不会使用默认的prop
强制执行错误
.filter((键)=>newProps[key]==未定义)
.forEach((键)=>{
newProps[key]=(defaultProps as any)[key];//暂时转换为any
});
}
将新道具作为EnforcedDefaultProps返回;
};
用法.ts:
接口是共享格式{
前缀?:字符串,
后缀?:字符串,
}
导出接口IStringFormatOpts扩展ISharedFormatOpts{
maxLength?:数字,
}
导出常量defaultStringFormatOpts:DeepReadonly={
前缀:“”,
后缀:“”,
};
// ...
const options=useDefaults(选择IStringFormatOpts、defaultStringFormatOpts、[“前缀”、“后缀”]);
选项的解析类型为
Pick&required和defined
如果具有默认值的对象是内联的,那么它也可以正常工作,这样就不需要类型化常量。在阅读@jcalz建议并进行更多实验/简化后,这几乎可以动态地生成正确的类型:
类型.ts:
从“ts essentials”导入{StrictOmit};
需要和定义的导出类型={
[K中的P]-?:排除;
};
导出类型MappedObjValue={
[K输入A键和B键]:
A[K]扩展B[K]
从不
:K
};
导出类型OptionalKeys=(MappedObjValue)[keyof T];
导出类型KeyWorkerySof