This is the code I want to write
interface InputField{
formHeading:string,
isText:boolean,
fields:any[]
}
interface InfoField{
formHeading:string,
isText:boolean,
textData:string[]
}
let testInfoField: InputField|InfoField;
testInfoField = {
formHeading : "hello",
isText : true,
textData : ['hi', 'hello']
};
console.log(testInfoField.textData)
// Works fine here
let testInputField: InputField|InfoField;
testInputField = {
formHeading : "Hi",
isText : false,
fields: [1,2,3,4]
}
console.log(testInputField.fields);
// Works fine here
const func = (Field:InfoField|InputField) =>{
if(Field.isText){
console.log("TextField text", Field.textData);
// Error in using Field.textData now
}
else{
console.log("Input Field", Field.fields);
// Error in using Field.inputField now
}
}
So, according to what I know in Typescript using union means you can use any of the interfaces. So, why it's not working in the function func? The error I got was :
Property 'textData' does not exist on type 'InputField | InfoField'. Property 'textData' does not exist on type 'InputField'. Property 'inputField' does not exist on type 'InputField | InfoField'. Property 'inputField' does not exist on type 'InputField'.
Can anyone tell me the reason for this? If I am using textData, then that means I want to use the InfoField interface, not InputField. It shouldn't matter if it doesn't exist on the InputField.
The function parameter value will automatically come as one of the two choices.
Why when used as a parameter, it is demanding a combined object? It's like it creates a big object consisting of all values of InfoField and InputField.
The problem is that both of your types have isText: boolean
, so either of them could have true
or false
for that, so if (Field.isText)
doesn't narrow the union type.
You need to declare the type of isText
as a literal true
or false
in order to create a discriminated union:
interface InputField{
formHeading:string,
isText:false, // ***
fields:any[]
}
interface InfoField{
formHeading:string,
isText:true, // ***
textData:string[]
}
Side note: The playground link shows that using Field.textData
works with the change. Using Field.inputField
still doesn't work, because neither of the union types has a property called inputField
. You probably meant fields
.