Думаю, я смог предложить решение вашей проблемы. К сожалению, из-за языковых ограничений он может быть не очень элегантным, но и неплохим.
К сожалению, ключевое слово « this » нельзя использовать в качестве тип, поэтому его нельзя использовать в дженериках, как указано в других ответах. В вашем случае вы можете переписать свой код, и вместо « this » просто используйте текущий тип, НО, это не будет «гарантией» того, что объекты внутри вашей таблицы будут одного типа, что вы описали как необходимые.
К сожалению, в JavaScript / TypeScript вы не можете гарантировать, что объекты в любом общем c коллекции относятся к тому же типу «по типам», потому что TypeScript не предоставляет таких инструментов, как ковариация, контравариантность и инвариантность. Вы должны обеспечить это с помощью кода и проверок. Это известная проблема, например, в обещаниях, где вы можете возвращать типы, которые вам не следует. (По крайней мере, это то, что я знаю и нашел только сейчас, не уверен на 100%)
Чтобы создать инвариантную таблицу, в которой все элементы одного типа, мы должны проверить все введенный элемент. Я предложил одну возможную модель, в которой каждая таблица принимает определяемую пользователем функцию, которая проверяет, какие типы могут быть разрешены, а какие запрещены:
interface TypeGuard<T>
{
(inputObject: T): boolean;
}
// Generic part
class SingleTypeTable<T>
{
private typeGuard: TypeGuard<T>;
constructor(typeGuard: TypeGuard<T>)
{
this.typeGuard = typeGuard;
}
Add(item: T)
{
//Check the type
if (!this.typeGuard(item))
throw new Error("I do not like this type");
//...
}
}
Персональная охрана работает следующим образом:
const personGuard: TypeGuard<Person> = function (person: Person): boolean
{
return person instanceof Person;
}
personGuard(new Person(...)); //true
personGuard("string" as any as Person); //false
Теперь вы можете создавать своих моделей и людей следующим образом:
// Some abstract model
abstract class Model<T>
{
constructor(
public readonly id: number,
public table: SingleTypeTable<T> //Table of models
)
{
}
}
// Example: a table of Person objects
class Person extends Model<Person>
{
constructor(
id: number,
table: SingleTypeTable<Person>,
public name: string
)
{
super(id, table);
}
}
//Usage
const personTable = new Table<Person>(personGuard);
const person = new Person(0, personTable , 'John Doe');
Я понимаю, что мог немного изменить структуру вашей модели, но я не знаю вашей общей картины, и я уверен, что если вам нравится это решение, вы можете изменить его по своему вкусу, это всего лишь прототип.
Надеюсь, это то, что вам нужно.
Эта часть моего ответа пытается объяснить мою теорию о том, почему вы не можете использовать ключевое слово this в конструкторе в качестве типа параметра.
Прежде всего, вы не можете использовать this как тип в функции. Вы не можете этого сделать:
function foo(a: this) {} //What is "this"? -> Error
Прежде чем я объясню дальше, нам нужно вернуться к равнине JavaScript. Один из способов создания объекта - «создать экземпляр функции», например:
function Animal(name) { this.name = name; }
var dog = new Animal("doggo");
Это почти то, для чего скомпилированы классы TypeScript. Видите ли, этот объект Animal является функцией, но также и конструктором для объекта Animal.
Итак, почему вы не можете использовать ключевое слово this в конструкторе TypeScript? Если вы посмотрите выше, конструктор компилируется в функцию, а параметры конструктора - это всего лишь некоторые параметры функции, и они не могут иметь тип this.
Однако компилятор TypeScript может для определения типа «this» используется даже параметр конструктора. Это, безусловно, хорошее предложение для команды TypeScript.