在被这个问题困扰了一年后,我正在重新审视这个问题.我不知道如何简洁地框定这个问题,所以请告诉我.
问题:我想通过其kind
属性的值来缩小嵌套对象的联合类型.然而,kind
字段是可选的,因为默认情况下它应该是"string"
.
TField
型(简化):
type TField = {
field: string;
name: string;
placeholder?: string;
required?: boolean;
}& (
| { kind: "string"; value?: string; block?: boolean }
| { kind: "password"; value?: string }
| { kind: "email"; value?: string }
| { kind: "number"; value?: number }
| { kind: "boolean"; value?: boolean; inline?: boolean; toggle?: boolean }
)
// ----- EDIT: I want the "name","field","kind" to be optional
// ----------- By default: "kind" should be 'string'
type PartialBy<T,K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>
type TLabeledField = PartialBy<TField, "name"|"field"|"kind">
type TFieldCluster = {
[key: string]: TLabeledField;
};
function makeFields(cluster: TFieldCluster){
const fieldMap = Object.entries(cluster).map(([str, path]) => {
let label = str;
let name,field;
let required = false;
if (label.endsWith("*")) {
required = true
label = label.slice(0,-1)
}
if (label.startsWith("$")){
field = label.slice(1);
name = label.replace(/([A-Z])/g, " $1").toLowerCase();
} else {
field = label // <-- will fix
name = label
}
return [
field,
{
type: "string",
name,
field,
required,
...path,
},
];
});
return Object.fromEntries(fieldMap);
}
const fields = makeFields({
title: {},
subtitle: {kind:"boolean", toggle: true}, // <-- SHOULD BE VALID BECAUSE I SPECIFIED 'KIND'
about: { block: true },
count: { kind:"number", block: true }, // <-- INVALID: 'BLOCK' ISN'T ON NUMBER!
})