Я очень новичок в Typescript, просто изучаю, как преобразовать наш существующий код JS. Мой подход (который вполне может быть ошибочным) состоит в том, чтобы сделать минимум, чтобы просто заставить его работать в TypeScript, а затем постепенно преобразовать его в соответствии с «лучшими практиками».
Кажется, я упал на первом барьере.....
У меня есть следующий TypeScript, использующий jQuery (в приложении ASP.NET .NET5).
interface MyInterface {
prop1: string;
prop2: number;
}
const something = {
currentThing : MyInterface,
init: (): void => {
//
}
};
$(something.init);
Итак, идея в том, что когда страница загружается, something.init
будет выполняться. Это настроит такие вещи, как обработчики событий через селекторы jQuery и т. д. и т. д. Кажется, что вся эта часть работает нормально.
Однако...
В какой-то момент сработает обработчик событий, и я создам новый объект, который будет реализовывать MyInterface
. Мне нужно будет сохранить это (установив его как значение свойства/поля currentThing
), чтобы к нему можно было получить доступ для будущих событий.
Однако Typescript не любит строку currentActivity: MyInterface,
, и я получаю сообщение об ошибке:
«MyInterface» относится только к типу, но здесь используется как значение.
Я рекомендую вам ввести свой something
объект, используя новый интерфейс, как :
interface MyInterface {
prop1: string;
prop2: number;
}
interface Something {
currentThing: MyInterface;
init: () => void;
}
const something: Something = {
currentThing: {
prop1: 'foo',
prop2: 5,
},
init: (): void => {
//
},
};
console.info(something.init);
Объект следует структуре ключ-значение, Typescript понимает текущее определение объекта как
const something = {
// key value
currentThing : MyInterface,
};
а поскольку MyInterface
не является допустимым значением, будет выдана указанная ошибка.
Что вам нужно сделать в этом случае, так это определить типы для объекта something
, введя его свойства следующим образом:
interface MyInterface {
prop1: string;
prop2: number;
}
interface SomethingInterface {
currentThing : MyInterface;
init: () => void
}
const currentThing = { prop1: 'aStringValue', prop2: 12345 };
const something: SomethingInterface = {
currentThing,
init: (): void => {
//
}
};
$(something.init);
Я попробовал вышеизложенное (что работает), но со следующей адаптацией. Я хотел бы услышать, считают ли мою адаптацию хорошей практикой или нет... Я изменил const currentThing = { prop1: 'aStringValue', prop2: 12345 };
на const currentThing: MyInterface = null;
, так как не хотел создавать фиктивный объект. Я также не был уверен, должно ли это быть const
... В функции init
я мог установить его с помощью something.currentThing = { prop1: "abc", prop2: 12345 };
и получить позже.
Думали ли вы использовать class
? Например, вы можете заменить init()
на constructor()
, а затем вызвать $(new Something(currentThing))
.
Как заявляли другие, вы не можете использовать типизацию для полей внутри литерала объекта. При необходимости я делаю его более читабельным, используя класс, и экспортирую константу, используя экземпляр этого класса.
Пример:
interface MyInterface {
prop1: string;
prop2: number;
}
class Something implements MyInterface {
public Something(public prop1: string, public prop2: number) {
}
init(): void {
}
}
export const something = new Something('value1', 10);
$(something.init);
Вы не можете назначать типы свойствам внутри литерала объекта. Вам нужно назначить тип для этого объекта
something
, например, какconst something: { currentThing: MyInterface, init: () => void } = { /* ... */}
. Также, вероятно, неплохо извлечь этот интерфейс.