Допустим, у меня есть тип союза Vehicle
, который выглядит так:
interface Car {
color: string;
doors: number;
wheels: number;
}
interface Plane {
color: string;
wings: number;
}
type Vehicle = Car | Plane;
Я хочу (1) извлечь из этого объединения типы, которые расширяют аргумент данного типа (это может быть легко достигнуто с помощью служебного типа Extract
) и (2) исключить из извлеченного типа(ов) ключи того же аргумента типа . Вот желаемый результат:
type Result1 = ExtractOmit<{ wheels: number; }>;
// This should give me the result of Omit<Car, "wheels">:
// { color: string; doors: number; }
type Result2 = ExtractOmit<{ wings: number; }>;
// This should give me the result of Omit<Plane, "wings">:
// { color: string; }
type Result3 = ExtractOmit<{ foo: number; }>;
// This should produce an error since foo is neither in Car nor Plane
Вот неудачная попытка:
type ExtractOmit<T> = Omit<Extract<Vehicle, T>, keyof T>;
// T extends what?
Правая часть кажется мне правильной, но я не могу понять, как поставить левую.
Любое предложение?
interface Car {
color: string;
doors: number;
wheels: number;
}
interface Plane {
color: string;
wings: number;
}
type Vehicle = Car | Plane;
type OmitExtract<T extends Partial<Vehicle>> = Omit<Extract<Vehicle, T>, keyof T>;
type Result = OmitExtract<{ wheels: number; }>;
type Result1 = OmitExtract<{ wheels: number; }>;
// This should give me the result of Omit<Car, "wheels">:
// { color: string; doors: number; }
type Result2 = OmitExtract<{ wings: number; }>;
// This should give me the result of Omit<Plane, "wings">:
// { color: string; }
Вышеупомянутое, похоже, работает так, как ожидалось.
Ключевыми элементами здесь являются использование «Автомобиля» (я заметил, что вы использовали Элемент ранее) и наличие T, расширяющего Partial слева, чтобы дать ему супертип, необходимый для извлечения, чтобы знать, из чего правильно извлекаться.
Обновлено: ссылка на игровую площадку
Вам нужно использовать type Vehicle = Car | Plane;
согласно сообщению ОП. Оригинальная игровая площадка OP имела неправильный код с type Vehicle = Car & Plane
, что давало неправильный результат, как на вашей игровой площадке. Union — это то, что необходимо в Vehicle для правильной настройки Vehicle.
Спасибо! Да, извините за путаницу с Element
, я имел в виду Vehicle
, как вы догадались.
Я заметил, что есть один пограничный случай, который не охвачен этим. Это когда { color: string; }
передается в качестве аргумента. Поскольку и Car
, и Plane
расширяют { color: string; }
, я ожидаю, что результатом будет объединение тех (из которых color
будет опущено): { doors: number; wheels: number; } | { wings: number; }
. Но все, что я получаю, это {}
. Любая идея, как мы могли бы принять этот случай во внимание?
Все, что нам нужно, это дистрибутив Omit (см. stackoverflow.com/questions/57103834/…).
Как раз собирался опубликовать то же самое после того, как наткнулся на поток stackoverflow! Надеюсь, это сработало. Сегодня мы узнали намного больше о типах полезностей ТС, ха-ха.
В общем, я обнаружил, что есть много мест, в которых машинописный текст не допускает хорошего разделения Union (т.е. имеет дело с явным «A | B» как типом, когда дело доходит до проверки равенства/присваивания).
На самом деле вам даже не нужен «T extends Partial<Vehicle>», если только вы действительно не хотите ограничить ввод супертипа T. Наличие транспортного средства справа — это то, что наиболее важно для настройки типа утилиты Extract.