当我尝试使用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'.
这将使程序员指向正确的缺失字段。
是否有可能以这样的方式编写类型:构造错误类型时返回的错误消息指向正确的缺失字段?
让我给我2美分,希望有人比我更聪明(coff @basarat)可以告诉你更酷的东西:-)
我不确定那些受歧视的工会能不能给你带来你在这里所拥有的一切。用户定义的类型保护可以。让我解释。你的对象大致是这样的:
interface NotTheTypeSafetyYouHopedFor {
discriminant_1: boolean;
extra_field_1?: boolean;
discriminant_2: boolean;
extra_field_2?: boolean;
}
但是你想要更多地强制执行这些类型。因此,让我们忘记discriminant_2
和extra_field_2?
存在来简化问题。噗!他们走了。
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
,那么它可能适合您的需求吗?希望有所帮助。吉达说“嗨”:-)