Я хочу получить подмножество конкретных/предопределенных свойств, используя Pick<Partial<Type>, Keys> на предоставленном Type. Предопределенные/конкретные свойства могут существовать, а могут и не существовать в предоставленном Type, но если их нет, нам не должно быть разрешено назначать их для возвращаемого типа.
Я попытался создать тип SubsetPick<T extends Partial<PropertyType>> = Pick<T, Keys>, но, вероятно, из-за типа Partial<PropertyType> он возвращает Keys, указанный в Pick<T, Keys>, даже если они не существуют в предоставленном Type.
Вот пример, воспроизводящий то, что я пытаюсь сделать:
interface Properties {
name: string;
animal: boolean;
plant: boolean;
fly: boolean;
swim: boolean;
walk: boolean;
}
type Bird = Pick<Properties, 'name' | 'animal' | 'fly'>;
// this doesn't work
type SubsetPick<T extends Partial<Properties>> = Pick<T, 'fly' | 'swim' | 'walk'>
// bad: we can assign properties `swim` and `walk` that don't exist on type `Bird`
const birdSubset: SubsetPick<Bird> = {
fly: true,
swim: true, // no error
walk: true, // no error
}
см. предыдущий комментарий. Может быть, вы ищете что-то вроде ссылку на игровую площадку , где вы явно запрещаете свойства, которые вы не выбираете? Но даже в этом случае я предполагаю, что вы хотите, чтобы растение было {}, а не undefined. Я близко? Я мог бы написать ответ или найти повторяющийся вопрос, если это то, что вы ищете. Если нет, пожалуйста отредактируйте, чтобы уточнить намерение.
@jcalz тип Plant не имел значения и мог привлечь много внимания к тому, чего я пытаюсь достичь. Я обновил фрагмент, чтобы попытаться более четко представить то, что я хочу... Я хочу иметь возможность получить подмножество конкретных свойств, используя Pick<Type, Keys> прилагается Type
Однако ваш ConditionalPick не «работает», это просто пустяк. Вы можете написать const bird: Bird = и получить желаемое поведение в обоих случаях, как показано по ссылке на игровую площадку. В чем проблема?
ConditionalPick не помогает продемонстрировать то, что вы ищете. Не могли бы вы посмотреть PickOnly в ссылку на эту игровую площадку и сообщить мне, это то, что вы ищете, или нет? Я полагаю, вы могли бы разделить его на оригинал Pick, а затем позже вернуться и попытаться исключить другие элементы, как показано в этой ссылке на игровую площадку, но я не уверен, что это вам дает. В любом случае, пожалуйста, посмотрите на них и дайте мне знать, так как я думаю, что одно или оба могут быть тем, чего вы пытаетесь достичь.
@jcalz, спасибо, что приложили некоторые усилия к моему вопросу, но я считаю, что вы слишком много внимания уделяете образцу и пытаетесь понять его смысл, тогда как я пытался представить только фиктивные типы. Я скорректировал начало проблемы, чтобы объяснить, что я хочу иметь возможность получать подмножество определенных ключей, ЕСЛИ они существуют в указанном типе. Надеюсь, это имеет больше смысла...
Пожалуйста, прочитайте мой предыдущий комментарий и ответьте на него конкретно.
Спасибо @jcalz, ваша игровая площадка не решила мою проблему, но вдохновила меня копать в другом направлении, и я нашел ответ
Боюсь, ваш ответ не имеет для меня особого смысла, как и вопрос. Было бы полезно узнать, какие именно типы ввода/вывода вы ищете, но на данный момент я полагаю, что дальнейшие комментарии и правки вряд ли будут плодотворными, поэтому я воздержусь от этого. Извините, мы не смогли эффективно общаться!
Извините, если это было недостаточно ясно, но я ценю время и усилия, которые вы вложили в это... вы помогли мне найти решение.






Я понял это, вдохновившись примерами игровых площадок, представленными в комментариях @jcalz...
Используя Extract<Type, Union>, можно извлечь только те ключи, которые можно назначить Type, и избежать наличия неназначаемых свойств в возвращаемом типе. Таким образом, вместо использования Pick<Type, Keys> вы можете создать возвращаемый объект правильного типа.
interface Properties {
name: string;
animal: boolean;
plant: boolean;
fly: boolean;
swim: boolean;
walk: boolean;
}
type Bird = Pick<Properties, 'name' | 'animal' | 'fly'>;
// this works
type SubsetPick<T extends Partial<Properties>> = {
[P in Extract<keyof T, 'fly' | 'swim' | 'walk'>]: T[P];
};
// good: we can only assign property that exists on type `Bird`
// and that are part of the subset declared in `SubsetPick`
const birdSubset: SubsetPick<Bird> = {
fly: true,
swim: true, // error
}
Учитывая ваш пример, это имеет мало смысла. Вы можете заменить его всего на type GenericPick<T> = T, и вы все равно получите сообщение об ошибке swim. См. ссылку на эту игровую площадку . Более того, ваша версия Extract фактически удаляет из типа такие вещи, как name, поэтому вы получаете сообщение об ошибке, как показано в этой ссылке на игровую площадку. Это действительно то, что вы пытаетесь сделать? Если это так, вам следует отредактировать вопрос, чтобы сделать это явным.
Извините, я не знаю, как сделать это более явным, поскольку это указано в верхней части описания: «Я хочу получить подмножество конкретных/предопределенных свойств... предопределенные/определенные свойства могут существовать, а могут и не существовать». по предоставленному типу, но если они этого не делают, нам не должно быть разрешено назначать его для возвращаемого типа». но если у вас есть идеи, как сделать это более понятным, не стесняйтесь.
Я не понимаю, в чем цель. Ваш
InferPick<T>по сути простоT, но дляPlantэтоundefined. Но... вы хотитеconst plant: InferPick<Plant> = undefined, а неconst plant: InferPick<Plant> = {}? Я вообще не вижу в этом пользыPick.