У меня есть библиотека, которая записывает простые объекты JS в хранилище. Все эти объекты имеют типы. Я использую дискриминационный союз с общим свойством "type"
.
Проблема в том, что код, использующий эту библиотеку (тогда в node_modules/
), не может обновить объединение.
Я только что переключил проект с Flow на TypeScript. В Flow я «решил» это, предоставив глобальный тип в flow-typed/
. У меня был пустой глобальный тип в каталоге flow-typed/
кода библиотеки, но он перезаписывается (фактически, весь файл игнорируется) приложениями, имеющими глобальные определения flow-typed/
.
Однако в TypeScript я не думаю, что у меня может быть как (пустой) локальный тип, так и включаемый в определение типа объединения, который позже будет перезаписан приложением?
Я прочитал довольно много похожих вопросов, но они всегда были немного нерешительными, и предложенные решения не сработали, или, может быть, я просто не понимаю, как переписать их для моего случая. Одно из отличий состоит в том, что мой собственный вариант использования кажется еще более простым: никаких классов, ничего сложного, просто набор простых объектов JavaScript .
Вот ссылка на игровую площадку с примером подхода (который терпит неудачу).
Вот код, немного отличающийся от примера, не показывающий предпринятый подход, а только то, что есть:
// ============================================================
// LIBRARY
// ============================================================
// Core (plain) object types defined within the library itself
interface O1 {
type: 'O1';
a: string;
}
interface O2 {
type: 'O2';
b: number;
}
type oUnion = O1 | O2;
// Let's have a function to test the union on
declare function libraryFn<T extends oUnion>(p: T): T;
// Works (good)
const { b } = libraryFn({ type: 'O', b: 42 });
// Doesn't work (good)
libraryFn({ type: 'noSuchType' });
// ============================================================
// CODE THAT USES LIBRARY
// ============================================================
// HOW DO I ADD THIS TO THE UNION?
interface MyType {
type: 'myO1';
someProp: string;
}
const o: MyType = { type: 'myO1', someProp: 'a word' };
const {someProp} = libraryFn(o);
К сожалению, подход, использующий универсальный член, использованный в этом примере, не работает.
Конечно, я мог бы довольно легко заставить его работать, включив в него члена профсоюза общего характера, но это сделало бы весь дискриминационный союз бесполезным. Прямо сейчас, когда функция, принимающая объединение, получает один конкретный член объединения, ее точный тип члена отражается в возвращаемом типе. Поэтому, если элемент имеет тип "Person"
со свойством email
, тогда средство проверки типов знает, что возвращенный объект будет иметь свойство email
, поскольку оно может решить, какой именно член объединения используется здесь.
Я экспериментировал с множеством подходов, и все, что мне удалось достичь, - это постоянно увеличивающаяся сложность, но без решения. Хакерский подход, который я использовал с Flow, перезаписывая глобально определенную переменную типа в приложении, кажется наименее дурацким, но а) я не знаю, как сделать то же самое в TS, б) я не знаю, есть ли лучше?