typescript - 打字稿条件验证取决于字段可空性
问题描述
我确实有以下代码:
type DomainFieldDefinition<T> = {
required?: boolean
}
type DomainDefinition<F, M> = {
fields?: { [K in keyof F]: DomainFieldDefinition<F[K]> },
methods?: { [K in keyof M]: M[K] & Function },
}
type User = {
id: string,
name?: string
}
export const User = createDomain<User>({
fields: {
id: { required: true },
name: {},
},
});
我正在尝试验证required
传递给createDomain
字段方法的定义对象中的键是否具有与其所基于的类型的必需性相匹配的值(此处,User
);理想情况下在编译时。
我感觉条件类型可能有助于这样做,但我找不到基于必要性的方法。具体来说,我试图限制required
为:
true
如果该字段不可为空,false
或未定义,如果是
有什么提示吗?
解决方案
使用此处定义的类型作为示例,我们可以创建一个条件类型,如果该字段是必需的,则field
类型将是类型{ required : true }
或{}
其他类型:
type DomainDefinition<F, M> = {
fields?: {
[K in keyof F]: ({} extends { [P in K]: F[K] } ? {} : { required: true }) & {} // Intersect with other properties as necessary
},
methods?: { [K in keyof M]: M[K] & Function },
}
type User = {
id: string,
name?: string
}
function createDomain<T>(o: DomainDefinition<T, any>) {
return o;
}
export const User = createDomain<User>({
fields: {
id: { required: true },
name: {},
},
});
注意这将测试可选性(?
修饰符)它不会测试可空性(| null | undefined
)取决于您的用例,这可能重要也可能不重要。
同样有趣的可能是这个答案,readonly
它对修饰符进行了测试。使用它,您还可以添加一个isReadonly
字段:
type IfEquals<X, Y, A, B> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? A : B;
type DomainDefinition<F, M> = {
fields?: {
[K in keyof F]:
({} extends { [P in K]: F[P] } ? {} : { required: true })
& IfEquals<{ [P in K]: F[P] }, { -readonly [P in K]: F[P] }, {}, { isReadonly: true }>
},
methods?: { [K in keyof M]: M[K] & Function },
}
type User = {
id: string,
readonly name?: string
}
function createDomain<T>(o: DomainDefinition<T, any>) {
return o;
}
export const User = createDomain<User>({
fields: {
id: { required: true },
name: { isReadonly: true },
},
});
如果要过滤掉某些属性,例如函数,则必须将所有出现的 替换F
为过滤的F
。为了简单起见,只需定义一个额外的类型别名:
type NonFunctionPropertyNames<T> = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T];
type DomainPropertyHelper<F> = {
[K in keyof F]: ({} extends { [P in K]: F[K] } ? {} : { required: true }) & {} // Intersect with other properties as necessary
};
type DomainDefinition<F, M> = {
fields?: DomainPropertyHelper<Pick<F, NonFunctionPropertyNames<F>>>,
methods?: { [K in keyof M]: M[K] & Function },
}
推荐阅读
- javascript - JavaScript:通过原型向 DOM-Object 添加方法 - 例如:Object.defineProperty(Object.prototype, ...)
- python - TypeError:print() 中的格式字符串参数不足
- r - 面板数据的滚动窗口回归
- javascript - 元素单独加载jquery
- java - 如何使用 APACHE TIKA 将 PDF 文件转换为带有样式的 HTML
- c++ - 如何用字符串填充数组?
- mongodb - MogoDB findAndModify 返回 WriteResult
- html - Angular Mat-Select - opensChange 返回未定义
- python - 在 python 中使用 elementtree 提取 XML 节点文本时出错
- java - 杰克逊为对象抛出 UnrecognizedPropertyException 但“additionalProperties”设置为 True