I have a function that takes parameters of similar structure and inside the function uses type guards to figure out the type of parameter passed in.
type Ex1 = {
contents: 'contents',
param1: 'yes'
}
type Ex2 = {
contents: 'contents',
param2: true
}
type Ex = Ex1 | Ex2;
export const exampleFunc = (example: Ex): Ex => {
const isEx1 = (unknownExample: Ex): unknownExample is Ex1 => {
return (unknownExample as Ex1).param1 === undefined ? false : true;
}
const execute = (): Ex => {
if (isEx1(example)) {
return example;
}
return example;
}
return execute()
}
In my actual application, a complex object of a different type is returned, but in this example, i simply return the same object.
When I execute the function
const ex1: Ex1 = {
contents: 'contents',
param1: 'yes'
}
const test = exampleFunc(ex1);
In my IDE, I can see that TS correctly understands that example
in the following block
if (isEx1(example)) {
return example;
}
is of the correct type
(parameter) example: Ex1
You can see that the object assigned to example
is returned from the function and in this case assigned to test
.
However, despite understanding the correct type in the return blocks, Typscript doesn't then assign test
as type Ex1
and instead assigns it as the more broad type Ex
.
const test = exampleFunc(ex1);
which means that the following throws an error
test.param1
Property 'param1' does not exist on type 'Ex'.
Are type guards only useful in the current execution block or am I misunderstanding their use?
Narrowing only applies to the local scope in which it occurs. Since your exampleFunc
declares that it returns an Ex
, the type system will treat it as an Ex
regardless of what happens inside the function.