Chic
Chic

Reputation: 10509

How to cast TypeScript type in javascript using JSDoc

When using TypeScript to check JavaScript code, how do you cast to a different type than is inferred? Typescript has the <Type> and as Type syntax but these aren't valid in JavaScript.

/**
 * @param {{id: string, value: number}} details - object with required properties
 */
function stringifyObject(details) {
  return `${details.id}: ${details.value}`;
}

const testValue = {id: 'no-value'};
stringifyObject(testValue); // want to cast testValue to ignore missing property
stringifyObject(/** @type {any} */ testValue); // this doesn't work

Upvotes: 35

Views: 11926

Answers (2)

Nor.Z
Nor.Z

Reputation: 1349

The Answer is already given in another post.
But to add more on the usage:

in short (repeated from details)

  • if you want to let the type cast be available in all the code lines below, use this

    node_curr = /** @type {Element} */ (node_curr);  // working for this line & all the lines below
    node_curr.outerHTML;
    

details

  • vv

        // #>>> an example usage
        const elt_main = $('<div></div>')[0];
        const treeWalker = document.createTreeWalker(elt_main, NodeFilter.SHOW_ALL);
    
        const arr_html_EltMain = [];
        let html_curr;
        let node_curr;
        while ((node_curr = treeWalker.nextNode())) {
          const nt = node_curr.nodeType;
          if (nt === Node.TEXT_NODE) {
            html_curr = /** @type {Text} */ (node_curr).textContent;
            arr_html_EltMain.push(html_curr);
          } else if (nt === Node.ELEMENT_NODE) {
            html_curr = /** @type {Element} */ (node_curr).outerHTML; // << the Type cast / autocompletion will only apply to this particular line, 
            //                                                          // any reference below this line will fall back to original Type
            //                                                          // also, if you hover to the variable, it appears to be still the old Type (though autocompletion works)
            arr_html_EltMain.push(html_curr);
          }
        }
    
        // #>>> 
        // @note: about the paranthesis -- only enclose it for the variable, not need to include the @type
        (/** @type {Element} */ (node_curr)).outerHTML;  // works, but unnecessary 
        /** @type {Element} */ (node_curr).outerHTML;    // use this
    
        // #>>> 
        // compare & the correct way to use 
        /** @type {Element} */ node_curr = node_curr;    // not_working                                        
        node_curr;                                       // not_working    
        (/** @type {Element} */ node_curr) = node_curr;  // not_working                                          
        node_curr;                                       // not_working    
        /** @type {Element} */ (node_curr) = node_curr;  // working only for this line
        node_curr;                                       // not_working    
        node_curr = /** @type {Element} */ node_curr;    // not_working                                       
        node_curr;                                       // not_working    
        node_curr = (/** @type {Element} */ node_curr);  // not_working                                         
        node_curr;                                       // not_working    
        node_curr = /** @type {Element} */ (node_curr);  // working for this line & all the lines below
        node_curr;                                       // working    
        node_curr;                                       // working    
        node_curr;                                       // working    
    
        // #>>> 
        // @note: if you want to let the type cast be available in all the code lines below, use this
        node_curr = /** @type {Element} */ (node_curr);  // working for this line & all the lines below
        node_curr.outerHTML;
    

other info (minor)

Upvotes: 5

Chic
Chic

Reputation: 10509

The /** @type */ comment is close. According to the TypeScript Handbook it just needs parenthesis around the value being cast.

TypeScript borrows cast syntax from Google Closure. This lets you cast types to other types by adding a @type tag before any parenthesized expression.

So in the original example you would write the following:

// Wrap value being cast in parenthesis 
stringifyObject(/** @type {any} */ (testValue));

Upvotes: 68

Related Questions