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?
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
*/
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.
@ekulabuhov life saver!
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.
For JSDoc code already using this, it'd be nice to have compatibility. Same for interface/implements....
(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 (?)
This would be really great as intersection types "&" are not going to to be supported by jsdoc.
Any valid @JSDoc solution yet?
Most helpful comment
You can use an Intersection Type notation there:
or
should both work.