С https://github.com/google/closure-compiler/wiki/Generic-Types#inheritance-of-generic-types, @extends MyColor<Red>
«исправляет» тип шаблона, а не распространяет его на наследуемый тип. Например, в
/**
* @constructor
* @template T
*/
var A = function() { };
/** @param {T} t */
A.prototype.method = function(t) { };
/**
* @constructor
* @extends {A<string>}
*/
var B = function() { };
/**
* @constructor
*
* @extends {B<number>}
*/
var C = function() { };
var cc =new C();
var bb = new B();
var bm = bb.method("hello");
var cm = cc.method(1);
cc.method(1)
приведет к TYPE_MISMATCH: actual parameter 1 of A.prototype.method does not match formal parameter
found : number
required: string
Вы можете попробовать изменить свой код на
/**
* @property {string} color
* @template {T}
*/
class MyColor {
constructor() {
this.color = 'unknown';
}
/**
* @returns {T}
*/
static makeColor() {
return /**@type {T}*/ new this.prototype.constructor();
}
}
/**
* @extends MyColor<T>
* @template {T}
*/
class Red extends MyColor {
constructor() {
super();
this.color = 'red';
}
}
const circle1 = Red.makeColor();
/**
* @extends Red<DarkRed>
*
*/
class DarkRed extends Red {
constructor() {
super();
this.level = 2;
}
darker() {
this.level += 1;
}
}
const circle = DarkRed.makeColor();
другое возможное решение - использовать @return {this}
вместо @template
(работает с 2018.2):
class MyColor {
constructor() {
this.color = 'unknown';
}
/**
* @return {this}
*/
static makeColor() {
return new this.prototype.constructor();
}
}
class Red extends MyColor {
constructor() {
super();
this.color = 'red';
}
}
class DarkRed extends Red {
constructor() {
super();
this.level = 2;
}
darker() {
this.level += 1;
}
}