#static-analysis #return-type #es6-class #ts-check
#статический анализ #возвращаемый тип #es6-class #ts-check
Вопрос:
Когда функция наследуется подклассом, я хочу, чтобы возвращаемый тип был таким, как если бы функция была определена непосредственно в подклассе.
Чтобы было понятно, код отлично работает во время выполнения. Но я хочу воспользоваться статической проверкой типов. Я получаю красные волнистые строки в VSCode и предупреждения от Google-Closure-Compiler. Я не уверен, связано ли это с моим кодом ES6 или с моими аннотациями типов.
Мой тривиальный пример классов ES6:
// @ts-check
"use strict";
export class db_row {
/**
* @param {number} id
*/
constructor(id) {
/** @type {number} */
this.id = id;
}
clone() {
return new db_row(this.id);
}
}
export class Channel_row extends db_row {
/**
* Constructor
* @param {*=} init
* @param {string=} name
* @param {string=} value
*/
constructor(init, name, value = '') {
let id = -1;
if (typeof init == 'object') {
id = init.id;
name = init.name;
value = init.value;
} else if (typeof init == 'number') {
id = init;
}
super(id);
this.name = name;
this.value = value;
}
clone() {
return new Channel_row(this.id, this.name, this.value);
}
}
export class db_table {
/**
* Constructor
* @param {Array<db_row>} table
*/
constructor(table) {
/**@type {Array<db_row>} */
this.table = table;
}
/**
*/
get_table_copy() { return this.table.map(item => item.clone()) }
/**
* @param {?number=} id
*/
get_row_by_id(id) {
const row = this.table.filter(item => item.id === id)[0];
if (row) return row.clone();
return null;
}
}
export class Channel_table extends db_table {
constructor() {
/**@type {Array<Channel_row>} */
let table = [];
super(table);
}
}
// Test code below:
/**
*
* @param {Channel_row} chan_row
*/
function print_chan_row(chan_row) {
console.log(chan_row.name);
}
let channel_table = new Channel_table();
let channel_row = channel_table.get_row_by_id(0); // hover reports that the type of channel_row is db_row, when it should be type Channel_row
print_chan_row(channel_row); // Red squiggly line error: Argument of type 'db_row' is not assignable to parameter of type 'Channel_row'. Type 'db_row' is missing the following properties from type 'Channel_row': name, valuets(2345)
console.log(channel_row.name); // Red squiggly line error: Property 'name' does not exist on type 'db_row'.ts(2339)
let channel_table_2 = channel_table.get_table_copy(); // hover reports that the type of channel_row is db_row[], when it should be type Channel_row[]
print_chan_row(channel_table_2[0]); // Red squiggly line error: Argument of type 'db_row' is not assignable to parameter of type 'Channel_row'.ts(2345)
Теперь, если я перемещу или скопирую функции get_row_by_id() и get_table_copy() в подкласс, ошибки типа исчезнут. Но я не хочу дублировать код без необходимости.
Как я могу объявить функции в родительском классе, чтобы их можно было повторно использовать в дочерних классах, но поддерживать проверку статического типа?
В качестве бонуса, могу ли я также обобщить функцию clone(), чтобы ее не нужно было переопределять в подклассах db_row?
Комментарии:
1. Вы спрашиваете о функции IDE (основные моменты или предупреждения в вашей IDE) или о функции TypeScript или функции Javascript? Я в замешательстве.
2. Я не использую TypeScript (может быть, я должен быть?). Я пишу на ES6 и переношу на ES5 с помощью Google-Closure-Compiler. Мои аннотации типов находятся в комментариях jsdoc. Флаг @ts-check дает мне статическую проверку в VSCode, что спасает мою жизнь!
3. Вы не ответили на мой вопрос. Вы спрашиваете о чем-то, что вы хотите, чтобы VSCode показал вам, что это не так? Или вы спрашиваете о проблеме программирования ES6?
4. @jfriend00 Я не знаю ответа на этот вопрос. Я предполагаю, что это либо ошибка в статическом анализе, предоставляемом VSCode, либо я написал неправильный код ES6.
5. /** * @возвращает {Channel_row[]} */ get_table_copy() { возвращает super.get_table_copy(); } — это делает типы счастливыми, но все еще кажется ненужным.