我正在尝试描述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]?
答案 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);
}
如果不使用相关问题中的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]
因此,通过将StringValue
和BooleanValue
扩展到一个公共kind
字段,它在[1]和[2]处都出错。
另一种方法是使用answer中的XOR
帮助类型