Один класс или интерфейс не может расширять или реализовывать объединение вещей, поэтому невозможно достичь того, чего вы хотите напрямую.Если вам действительно нужен один класс для поведения, подобного дискриминационному объединению, я бы подумал об использовании универсального класса, в котором ваше зависимое свойство имеет условный тип :
class Example<T extends C["thing"]> {
constructor(
public thing: T,
public otherThing: Extract<C, { thing: T }>["otherThing"]
) {}
}
В конкретном случае, когда свойство дискриминанта thing
является допустимым типом ключа (и 1 | 2
работает), вы можете использовать сопоставленных типов вместо условных типов (хотя я будусоздайте отображение условного типа, например:
type MappedOtherThing = {
[K in C["thing"]]: Extract<C, { thing: K }>["otherThing"]
};
class Example<T extends C["thing"]> {
constructor(public thing: T, public otherThing: MappedOtherThing[T]) {}
}
Extract<C, {thing: T}>["otherThing"]
использует служебный тип Extract
, чтобы найти члена C
, который может быть назначен{thing: T}
, а затем ищет его свойство otherThing
.
Любая из этих реализаций даст вам такое поведение:
const eA = new Example(1, "okay"); // Example<1>
eA.otherThing; // string
const a: A = eA; // okay
const eB = new Example(2, 12345); // Example<2>
eB.otherThing; // number
const b: B = eB; // okay
const c: C = Math.random() < 0.5 ? eA : eB; // okay
Надеюсь, что это поможет.Удачи!
Ссылка на код