Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support typedef inheritance with JSDoc #20077

Open
fongandrew opened this issue Nov 16, 2017 · 7 comments
Open

Support typedef inheritance with JSDoc #20077

fongandrew opened this issue Nov 16, 2017 · 7 comments

Comments

@fongandrew
Copy link

@fongandrew fongandrew commented Nov 16, 2017

TypeScript Version: 2.7.0-dev.20171116

Code

/**
 * @typedef {Object} Base
 * @property {String} baseProp
 */

/**
 * @typedef {Base} Child
 * @property {String} childProp
 */

/** @type {Child} */
const child = { baseProp: '' };

Expected behavior: Error. child is missing the childProp property.

Actual behavior: No error. The Child type is identical to the Base type and only requires a baseProp property. The childProp property definition is completely ignored.

Or maybe there's another way to do the equivalent of interface Child extends Base here?

@fongandrew

This comment has been minimized.

Copy link
Author

@fongandrew fongandrew commented Nov 16, 2017

For what it's worth, I also tried the following combinations. Both result in Child being typed as any.

/**
 * @typedef {Object} Child
 * @extends Base
 * @property {String} childProp
 */
/**
 * @typedef {Object} Child
 * @mixes Base
 * @property {String} childProp
 */
@ekulabuhov

This comment has been minimized.

Copy link

@ekulabuhov ekulabuhov commented May 29, 2018

You can use an Intersection Type notation there:

/**
 * @typedef {Base & {childProp: String}} Child
 */

or

/**
 * @typedef {Object} ChildType
 * @property {String} childProp
 *
 * @typedef {Base & ChildType} Child
 */

should both work.

@kasora

This comment has been minimized.

Copy link

@kasora kasora commented May 31, 2018

@ekulabuhov life saver!

@mmis1000

This comment has been minimized.

Copy link

@mmis1000 mmis1000 commented Jun 15, 2018

Although the & trick works most of time.
Some things will only work with interface instead of type

// won't work, and no workaround at all

/**
 * @typedef {number|ArrayjOfValue} value
 */

/**
 * @typedef {Array<value>} ArrayjOfValue
 */

/**
 * @type {value}
 */
var k1 = [1, [1]]
// works

type value = number | ArrayOfValue;

interface ArrayOfValue extends Array<value> {}

var k1: value = [1, [1]]

The interface in typescript is lazy evaluated.
And only checked when the value is actually encountered.
So, it can work as a guard to prevent the definition from expanding infinitely.

While the type is not.
And will be expanded completely at init time.
Making referring to itself not possible at all.

I think typedef in JSDOC extends from non Object Object type should be translate to a interface instead of a type definition.

Or it will make the JSDOC syntax lack a bunch of ability

But I don't have any idea whether it will break existing code or not. And whether interface can be a superset of type or not.

@brettz9

This comment has been minimized.

Copy link

@brettz9 brettz9 commented Jul 2, 2018

For JSDoc code already using this, it'd be nice to have compatibility. Same for interface/implements....

@myfonj

This comment has been minimized.

Copy link

@myfonj myfonj commented Feb 7, 2019

(Pardon perhaps silly question regarding JSDoc behavior in current VSCode.)

"Intersection Type notation" from ekulabuhov's comment somewhat works in current VSCode but only when used like

/**
 * @typedef movable
 * @property {function} moveMe
 */
/**
 * @typedef {movable & HTMLElement} movableElement
 */
/** @type movableElement */
var myElement = document.querySelector('#myElement');
myElement.moveMe; // OK, function
myElement.tabIndex; // OK, number
myElement.error_test; // OK, does not exist

But straightforward declaration of custom type with base type and custom property

/**
 * @typedef {HTMLElement} movableElement
 * @property {function} moveMe
 */

results in simply aliasing HTMLElement as movableElement but with no added property. (It is basically what OP describes.) So is it a bug or some reasonable behavior? Using TypeScript (hopefully) equivalent

type movableElement = HTMLElement & { moveMe: Function };
var myElement: movableElement = document.querySelector('#myElement');
myElement.tabIndex; // OK, number
myElement.moveMe; // OK, Function
myElement.error_test; // OK, does not exist

works as expected.

BTW, if that Intersection Type notation is standard and stable already, it should be probably mentioned in https://github.com/Microsoft/TypeScript/wiki/JsDoc-support-in-JavaScript (?)

@chriseaton

This comment has been minimized.

Copy link

@chriseaton chriseaton commented Sep 16, 2019

This would be really great as intersection types "&" are not going to to be supported by jsdoc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
9 participants
You can’t perform that action at this time.