Reputation: 1768
I have a similar situation,
type Field1Type = {
a: string;
}
type Field2Type = {
b: string;
c: number;
}
type ObjType = {
field: Field1Type | Field2Type
}
const field = {
b: ""
c: 0
}
const obj = { field } as ObjType
if (some_condition) {
// TS compiler errors out: Property 'b' does not exist on type 'Field1Type'.ts(2339)
console.log(obj.field.b)
}
Where I essentially have an object with an object field which can take different types.
When accessing the field properties, I get the TS warning for a valid reason since it doesn't know if that field type is either Field1Type
or Field2Type
.
That could be fixed as followed,
if (some_condition) {
const temp = obj.field as Field2Type
// TS compiler errors out: Property 'b' does not exist on type 'Field1Type'.ts(2339)
console.log(temp.b)
}
But it doesn't really look like a clean solution.
Question, is it possible to assert the field inside the condition in a nicer way?
Upvotes: 0
Views: 235
Reputation: 299
I don't know the design and architecture of your data structure, but it seems wrong to map two completely different types to same "field". I would rather create two separate properties to keep it clean. Something like
type ObjType = {
field1: Field1Type;
field2: Field2Type;
}
Having said that if you really have to put it in one field property, What you did is more or less correct. You can also do something like following
obj.field = <Field2Type>(obj.field);
If the types are not "either or" in your use-case (Meaning they are extensions instead of exclusive types) Then you can intersect them like this -
type Field2Type = Field1Type & {
b: string;
c: number;
};
And then your field in obj is by default Field2Type.
type ObjType = {
field: Field2Type
}
And then you don't need any explicit mapping.
And result -
But honestly, if these two types are exclusive, it is better to have two properties. That way it is much cleaner.
Upvotes: 1