I'm at my wits end with this. It seems like it should work, I've been wrestling with it for hours, but I'm not sure what's wrong. This is the smallest example I could come up with. I even have a type guard.
/** @typedef {{ a: string }} TypeA*/
/** @typedef {{ b: string }} TypeB*/
/** @typedef {(TypeA | TypeB) } TypeC */
/** @type {TypeC} */
let typeC;
console.log(typeC.b) // autocompletion for property b doesn't work
I get the error:
Property 'b' does not exist on type '{ a: string; } | { b: string; }'.
Property 'b' does not exist on type '{ a: string; }'.ts(2339)
TypeScript Union Type Narrowing To narrow a variable to a specific type, implement a type guard. Use the typeof operator with the variable name and compare it with the type you expect for the variable.
You can use most JSDoc type syntax and any TypeScript syntax, from the most basic like string to the most advanced, like conditional types.
The "property does not exist on type union" error occurs when we try to access a property that is not present on every object in the union type. To solve the error, use a type guard to ensure the property exists on the object before accessing it.
Intersection types are closely related to union types, but they are used very differently. An intersection type combines multiple types into one. This allows you to add together existing types to get a single type that has all the features you need.
I found that a jsdoc style type guard lets me access the properties of TypeC if I am able to duck type it as TypeB.
/** @typedef {{ a: string }} TypeA*/
/** @typedef {{ b: string }} TypeB*/
/** @typedef {(TypeA | TypeB) } TypeC */
/**
* @param {*} value
* @returns {value is TypeB}
*/
function typeIsB(value) {
return true;
}
/** @type {TypeC} */
let typeC;
if (typeIsB(typeC)) {
console.log(typeC.b) // no error, autocomplete works when typing typeC.b
}
Screenshot of autocomplete working:
I think you are looking for the intersection of A and B, not the union. Here is the typescript code for your issue fixed:
interface A {
a: string;
}
interface B {
b: string;
}
type C = A & B;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With