Вы близки, но проблема в том, что ваш T
является конкретным типом, а не параметром обобщенного типа c, и, следовательно, T extends { pointer: K } ? T : never
не распространяется по объединениям . Таким образом, T extends { pointer: K }
будет просто ложным для каждого варианта K
, и вы получите never[]
вместо того, что ищете.
Самый простой способ вернуть распределительные условные типы - использовать введите псевдоним в форме type Something<X> = X extends { pointer: K } ? X : never
, а затем вставьте Something<T>
. К счастью, встроенная утилита Extract<T, U>
типа уже работает таким образом. Итак, мы можем написать это:
type M = { [K in T["pointer"]]?: Array<Extract<T, { pointer: K }>> };
, что дает:
/*
type M = {
"/name"?: ({
readonly pointer: "/name";
readonly name: "N1";
} | {
readonly pointer: "/name";
readonly name: "N2";
})[];
"/zip"?: {
readonly pointer: "/zip";
readonly name: "Z1";
}[];
}
*/
Что, я думаю, ближе к тому, что вы хотите. Обратите внимание, что я сделал реквизиты необязательными, поскольку ваша константа m
не имеет всех реквизитов:
const m: M = {
"/name": [{ pointer: "/name", name: "N2" }]
}; // okay
Хорошо, надеюсь, это поможет; удачи!
Детская площадка ссылка на код