在打字稿中使用联合体类型时出现不确定的错误消息

时间:2019-12-19 16:27:01

标签: typescript

我正在尝试描述Firestore值的联合类型:

interface StringValue {
    stringValue: string;
}

interface BooleanValue {
    booleanValue: boolean;
}

type ValueType = StringValue | BooleanValue;
var value: ValueType = { booleanValue: false, stringValue: "null" }; // [1]

if (value.booleanValue) console.log(value); // [2]

我在[2]时遇到错误:

Property 'booleanValue' does not exist on type 'ValueType'.
  Property 'booleanValue' does not exist on type 'StringValue'.(2339)

尽管我希望在第[1]行发生错误,但错误的分配发生在哪里。那么,为什么[2]而不是[1]?

https://www.typescriptlang.org/play/index.html?ssl=1&ssc=1&pln=13&pc=1#code/JYOwLgpgTgZghgYwgAgMpiqA5gNTgGwFcUBvAWAChlrkBnDbPIiALjoZCwG5KBfSyqEixEKAEIB7CfghwQTYsnJUaAIyky5C1snXTZIHhX4VKYAJ4AHFNoAqVlAF40HXAUUAfZJP1b3EIwA3OChkYOY2OwdkZxJdDQNtNnh8WggAGnZMTiTkACIQQnx8POReI0EYZAAKcOIAOj1NeX8ASmQECRBafXr8CSxatqMgA

2 个答案:

答案 0 :(得分:1)

在尝试检查对象中是否存在属性时,最好使用in

if ('booleanValue' in value)
    console.log(value);

此检查不会产生错误。

另一方面,它不会为分配生成错误,因为Typescript会检查对象中是否存在最小属性,但是如果您添加更多项,TS会很满意。 Check this part of TS docs for more info

答案 1 :(得分:0)

我想出了一些足够的东西:

// makes all props undefined
type Undefined<T> = {
    [P in keyof T]: undefined;
};

type Values = {
    stringValue: string;
    booleanValue: boolean;
}

// picks Key prop from the Dict and marks the rest of them as undefined
type OnlyOne<Dict, Key extends keyof Dict> = Partial<Omit<Undefined<Dict>, Key>> & Pick<Dict, Key>

type StringValue = OnlyOne<Values, 'stringValue'>
type BooleanValue = OnlyOne<Values, 'booleanValue'>

var x: StringValue = { stringValue: 'q' }
var y: BooleanValue = { booleanValue: false }
var shouldFail: BooleanValue = {stringValue: 'a string', booleanValue: false} // fails


type ValueType = StringValue | BooleanValue;
var badValue1: ValueType = { booleanValue: false, stringValue: "null" }; // fails
var badValue2: ValueType = { foo: 'bar' }; // fails
var okValue1: ValueType = { booleanValue: true };
var okValue2: ValueType = { stringValue: 'string' };

if (okValue1.booleanValue) {
    var bv: boolean = okValue1.booleanValue; // ok here
    var sv: string = okValue1.stringValue; // fails, stringValues is undefined
    console.log(okValue1.stringValue);
}

playground


如果不使用相关问题中的Xor帮助类型,这将是可行的:

interface StringValue {
    kind: 'string',
    stringValue: string;
}

interface BooleanValue {
    kind: 'boolean',
    booleanValue: boolean;
}

type ValueType = StringValue | BooleanValue;
var value: ValueType = { booleanValue: false, stringValue: "null", kind: 'string' }; // [1]

if (value.booleanValue) console.log(value); // [2]

因此,通过将StringValueBooleanValue扩展到一个公共kind字段,它在[1]和[2]处都出错。

https://www.typescriptlang.org/play/index.html?ssl=12&ssc=82&pln=12&pc=68#code/JYOwLgpgTgZghgYwgAgMpiqA5gNTgGwFcUBvAWAChlrkBrUAEwC5kByAZw21YBpKbknTCFwFiLIdgDclAL6VKoSLEQoAQgHsN+CHBB4ipfjXohmbAEZade3sepXtu-WIgtHNkDIryKlMACeAA4oBsQAKsEoALxoXCJhKAA+yJpOeoneAG5wUMg5hiyJkSHIsSTIHs6JLPD47BA8gvGihcgARCCE+PjtTabmHC2syLLeijDIABQFxAB0VRmuAJTICBog7E5z+BpYMyveQA


另一种方法是使用answer中的XOR帮助类型