#javascript #typescript #generics #functional-programming #overloading
Вопрос:
Я работаю над реализацией некоторых функций в Typescript, которые я хотел бы перегрузить и которые также используют универсальные средства. Я совершенно сбит с толку этим результатом:
*Обратите внимание, что я удалил код, который не вызывает проблемы, поэтому, пожалуйста, не обращайте внимания на бесполезность фактических функций.
Это работает:
export function persistContactData<T>(
contactData: T,
callback?: () => void
): void;
export function persistContactData<T>(
{ contactData }: { contactData: T },
callback?: () => void
): void;
export function persistContactData<T>(
{ contactData }: { contactData: T },
callback?: () => void
) {
// implementation
}
Это не так (только в первом есть ошибка):
// *** Compile error: "This overload signature is not compatible with its implementation"
//
export function getPersistedContactData<T>(
contactId: string,
callback: (result?: T) => void
): void;
// No more errors, and if I remove the above signature everything is fine.
export function getPersistedContactData<T>(
{ contactId }: { contactId: string },
callback: (result?: T) => void
): void;
export function getPersistedContactData<T>(
{ contactId }: { contactId: string },
callback: (result?: T) => void
) {
// implementation
}
Я озадачен тем, в чем здесь проблема, но я предполагаю, что что-то связано с тем, как используется общий параметр? Но, похоже, это не должно иметь значения.
(Я использую машинописный текст 3.9.3)
Изменить: Я обновил без каких-либо неизвестных типов
Комментарии:
1. Что такое
PersistContactData
? Если это важно, не могли бы вы дать его определение? Если это не важно, не могли бы вы удалить его? В идеале, когда ваш пример кода помещается в автономную среду разработки, такую как игровая площадка TypeScript (ссылка) , единственными проблемами, которые могут возникнуть, должны быть те, о которых вы спрашиваете.2. Если я позвоню
getPersistedContactData("foo", x => x);
, какой, по-вашему, должнаcontactId
быть переменная внутри реализацииgetPersistedContactData()
? Это не будетstring
«а». Значение"foo"
не имеетcontactId
свойства, поэтому вы делаете что-то странное. Не уверен, в чем смысл этого, но, возможно, вам следует исправить это вот так … и если это не поможет, вы, возможно, захотите подробнее остановиться в вопросе о том, что вы пытаетесь сделать. Удачи!3. Хороший момент, я удалил все ненужные и неопределенные типы, так что теперь проблему будет легче увидеть.
Ответ №1:
Проблема в том, что универсальный параметр позволяет компилятору предположить, что форма может определять ожидаемый тип, поскольку фактическая реализация будет определять фактические формы параметров.
Это можно увидеть, если удалить все универсальные типы и вместо них использовать фактические типы.
Это сработает (но, вероятно, на самом деле это не то, что задумано):
export function persistContactData<T>(
contactData: T, // <---- What is T? ┐( ̄~ ̄)┌ Could be the right shape?
callback?: () => void
): void;
export function persistContactData<T>(
{ contactData }: { contactData: T },
callback?: () => void
): void;
export function persistContactData<T>(
{ contactData }: { contactData: T },
callback?: () => void
) {
// implementation
}
Этого не будет:
// Error
export function persistContactData(
contactData: string, // <---- string is not compatible with the implementation
callback?: () => void
): void;
export function persistContactData(
{ contactData }: { contactData: string },
callback?: () => void
): void;
export function persistContactData(
{ contactData }: { contactData: string },
callback?: () => void
) {
// implementation
}