I have an object, and I need to add some extra properties to it in some cases.
interface Item {
name: string
}
functi
What I think you want to do, is to determine some property relations. As it is wrong to just get different type and cast it as it would be another one. I think your Item
type can have some additional properties in some circumstances, and that we should model in the type definition!
Lets start from proper typing:
type ItemNoFoo = { name: string };
type ItemWithFoo = ItemNoFoo & {foo: string}
type Item = ItemNoFoo | ItemWithFoo;
I created Item as a union of ItemNoFoo
and ItemWithFoo
. Thanks that we can define two different states of our object.
Now I will create a function, guard function which will check if we are ItemNoFoo
or ItemWithFoo
states.
const hasFoo = (item: Item): item is ItemWithFoo => item.name === 'test';
Ok great so we can now ask if Item
has property foo or not in scope of one type ( as our type is just a union of two other types ).
The final code:
type ItemNoFoo = { name: string };
type ItemWithFoo = ItemNoFoo & {foo: string}
type Item = ItemNoFoo | ItemWithFoo;
const hasFoo = (item: Item): item is ItemWithFoo => item.name === 'test';
function addProp(obj: Item) {
if (hasFoo(obj)) {
obj.foo = 'hello'; // in if block obj is inferenced as ItemWithFoo!
}
}
Some more info about this approach you can find here - Sum types
If it happens that our function needs to create a new structure, so is like a - data creator, or data transformer, then we should look on it as in -> out
pipe. In types, in is ItemNoFoo
and out type is ItemWithFoo
| ItemWithFoo
( types definitions in point 1 ).
function transform(obj: ItemNoFoo): Item {
if (obj.name === 'test') {
return {
...obj,
foo: 'hello'
} // here we create new value with new type
} else {
return obj;
}
}
As you can see still union type Item
is handy as this function returns or unchanged ItemNoFoo
type instance or ItemWithFoo
.
Lets check the using of it:
function f(item: ItemNoFoo) {
const finalItem = transform(item); // type of finalItem is ItemWithFoo | ItemNoFoo
}
If further you want to be sure if you deal with one or another, then handy can be hasFoo
guard function (defined in solution 1) which will determine which of these two types the value is.