#javascript #jquery #angularjs #d3.js #typescript
#javascript #jquery #angularjs #d3.js #typescript
Вопрос:
У меня есть несколько разных ситуаций, когда я пытаюсь определить самодельное свойство для массива или объекта в typescript, но обычно получаю ошибку:
«Свойство x не существует для типа Object (или типа Array)»
Например, я использую typescript в Angular и имею определенную область действия на основе файла определения типа Angular:
scope:ng.IScope
Но затем, когда я пытаюсь создать новое свойство в области видимости, выполнив:
scope.anotherProperty = "string";
Я получаю ошибку, указанную выше. Я знаю, что могу решить это, выполнив одно из следующих действий:
scope["anotherProperty"] = "string";
или
(<any>scope).anotherProperty = "string;
Другой пример — когда у меня есть что-то подобное в моем графике d3:
function panZoomNode (node:any) {
for (var i = 0; i < renderedNodes.length; i ) {
if (node.id === renderedNodes[i].id) {
}
}
}
В идеале я хотел бы изменить этот параметр (node: any) на что-то вроде:
(node:Object)
Но когда я это делаю, я получаю сообщение об ошибке «идентификатор свойства не существует для типа Object». Я знаю, что могу исправить это с помощью решений, о которых я упоминал выше, но это кажется мне небрежным. Есть ли лучший способ или лучший способ typescript заставить их работать правильно как для массивов, так и для объектов?
Спасибо
Комментарии:
1. Можете ли вы наследовать от ng. Я думаю, добавить еще одно свойство в определение и использовать его? Последняя проблема вызвана тем, что объект не имеет свойства id . Либо вы оставляете его свободно набираемым с помощью any, либо создаете класс / интерфейс.
2. Да, я должен иметь возможность наследовать от этого, каков наилучший способ добавить определение тогда? Позволит ли это мне сделать что-то вроде «scope.anotherProperty = string». Кроме того, если бы я собирался добавить интерфейс, я бы хотел просто установить все свойства, которые потенциально может иметь объект узла, или если я просто использую id, мне лучше просто добавить id? а затем вызовите это в определении параметра. Спасибо
3. Я добавил ответ ниже. Вместо наследования от ng. Возможно, вы можете просто расширить его.
Ответ №1:
Вы можете добавить дополнительное свойство к ng.IScope
интерфейсу, добавив в свой код следующее:
interface ng.IScope {
anotherProperty?:string;
}
Это позволит вам вызвать
scope.anotherProperty = "string";
Не видя остальной части вашего кода и не зная, что node
на самом деле представляет, я могу только сказать, что для того, чтобы компилятор был доволен, вам нужно просто включить элементы, на которые вы ссылаетесь, в свой TS-код. Если вы все делали правильно, создайте класс, содержащий все члены. Если оно является производным от существующего класса или реализует существующий интерфейс, тогда вы должны наследовать от тех, которые указаны в вашем определении класса.
Редактировать: если вы еще этого не сделали, вам следует поискать определения D3 в репозитории DefinitelyTyped на GitHub. Предполагая node
, что это тип D3, вы можете использовать это для решения своей проблемы и избежать написания собственного класса.
Комментарии:
1. Да, в итоге я просто расширил ng. Я проверяю и добавляю дополнительные свойства, к которым мне нужно было получить доступ. Это работает нормально. Моему редактору не понравилось просто использовать интерфейс, как вы описали в своем ответе. Для узла я просмотрел определения типа D3, но в моем случае там ничего не работает для узла, поскольку я также использую dagre-d3 с определенными свойствами. Я только что создал интерфейс и добавил нужные мне свойства, которые сработали для меня. Спасибо