[英]Convert discriminated union (or array of object types) into a mapped type with a literal property as the key
[英]Mapped types: Make property required based on whether array of same object contains string literal
是否可以根据相同 object 的数组是否包含字符串文字来制作 object 属性?
type Operator = "A" | "B"
type SomeStruct = {
operators: Operator[];
someProp: string; // this should be required if operators include "A", optional if not
}
// desired result
const structWithA: SomeStruct = {
operators: ["A", "B"],
someProp: "" // correct, since operators contains "A", someProp is required
};
const structWithB: SomeStruct = {
operators: ["B"],
// currently errors, but desired outcome is that it should not error, since operators does not contain "A"
};
declare const structs: SomeStruct[];
structs.map(struct => {
if(struct.operators.includes("A")) {
// someProp is safely accessible
}
// since .includes has a narrow type signature, maybe another way to safely access someProp is needed
})
通过使用标识 function 来创建结构(以及区分其类型的谓词),您可以完成此操作:
type A = 'A';
type B = 'B';
type Operator = A | B;
type SomeStruct<T extends readonly Operator[]> = { operators: T; } & (
T extends readonly A[] ?
Record<'someProp', string>
: unknown
);
function craeteStruct <O extends readonly Operator[], T extends SomeStruct<O>>(struct: T): T {
return struct;
}
const structWithA = craeteStruct({
operators: ["A", "B"],
someProp: "",
});
const structWithB = craeteStruct({
operators: ["B"],
});
declare const structs: (SomeStruct<Operator[]>)[];
function includesA (struct: SomeStruct<Operator[]>): struct is SomeStruct<A[]> {
return struct.operators.includes('A');
}
structs.map(struct => {
if(includesA(struct)) {
struct.someProp; // string
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.