当我尝试同时使用Typescript的类型交集和区分的并集时,我正在运行似乎是错误的类型错误。
想法是:
一个对象应包含两个布尔值-discriminant_1
和discriminant_2
。如果这些判别字段中的任何一个为true
,则对象应包含一个额外的字段-分别为extra_field_1
和extra_field_2
。
这是有效对象的一些示例:
// Neither field is true - no extra fields
{ discriminant_1: false, discriminant_2: false }
// discriminant_1 is true - extra_field_1 present
{ discriminant_1: true, extra_field_1: true, discriminant_2: false }
// both discriminant fields are true - both extra fields present
{ discriminant_1: true, extra_field_1: true, discriminant_2: true, extra_field_2: true }
还有一个无效的对象,因为discriminant_2
是true
但缺少extra_field_2
{ discriminant_1: false, discriminant_2: true }
这会在预期的位置提供编译错误,但是在没有提供字段的情况下,这些错误会引起混淆。
对于以下对象:
{ discriminant_1: false, discriminant_2: true }
该类型无法编译,因为如果discriminant_2
为true
,则应在对象中指定extra_field_2
。但是类型错误是:
Type '{ discriminant_1: false; discriminant_2: true; }' is not assignable to type 'FullType'.
Type '{ discriminant_1: false; discriminant_2: true; }' is not assignable to type 'Discriminant1_True & Discriminant2_True'.
Property 'extra_field_1' is missing in type '{ discriminant_1: false; discriminant_2: true; }' but required in type 'Discriminant1_True'.
该错误消息表示尽管Discriminant1_True & Discriminant2_True
是discriminant_1
的事实,但推断出的类型仍然是false
,并指出实际上缺少extra_field_1
extra_field_2
丢失。
预期的错误消息是:
Type '{ discriminant_1: false; discriminant_2: true; }' is not assignable to type 'FullType'.
Type '{ discriminant_1: false; discriminant_2: true; }' is not assignable to type 'Discriminant1_False & Discriminant2_True'.
Property 'extra_field_2' is missing in type '{ discriminant_1: false; discriminant_2: true; }' but required in type 'Discriminant2_True'.
这将使程序员指向正确的缺失字段。
是否可以这样编写类型,使得构造错误类型时返回的错误消息指向正确的缺少字段?
答案 0 :(得分:0)
让我给我2美分,希望比我聪明得多的人( coff @basarat)可以告诉您更多更酷的东西:-)
我不确定受歧视的工会是否能为您提供您所追求的目标。用户定义的类型保护可以。让我解释。您的对象大致如下:
interface NotTheTypeSafetyYouHopedFor {
discriminant_1: boolean;
extra_field_1?: boolean;
discriminant_2: boolean;
extra_field_2?: boolean;
}
但是您想再强制一些类型。因此,我们通过忘记存在discriminant_2
和extra_field_2?
来简化问题。 of!他们走了。
interface False1 {
discriminant_1: false;
}
interface True1 {
discriminant_1: true;
extra_field_1: boolean;
}
type False1OrTrue1 = False1 | True1;
const exampleFalse1: False1 = { discriminant_1: false };
const exampleTrue1: True1 = { discriminant_1: true, extra_field_1: false };
function isTrue1(aFalse1OrTrue1: False1OrTrue1): aFalse1OrTrue1 is True1 {
return aFalse1OrTrue1.hasOwnProperty('extra_field_1')
}
function doSomething(aFalse1OrTrue1: False1OrTrue1) {
if (isTrue1(aFalse1OrTrue1)) {
console.log(aFalse1OrTrue1.extra_field_1); // succeeds as this is a True1
} else {
console.log(aFalse1OrTrue1.extra_field_1); // compile error as this is a False1
}
}
我怀疑这种方法可能无法直接根据您问题的性质(例如discriminant_2等)进行扩展
但是,如果对象中的每个属性都是False1OrTrue1
,那么也许满足您的需求?希望能有所帮助。圭达说“嗨”:-)