Это известное ограничение , что TypeScript неправильно различает свойства объекта (и параметры функции), которые отсутствуют от тех, у которых присутствует, но undefined
.Тот факт, что Partial<T>
допускает undefined
свойства, является следствием этого.Правильнее всего подождать, пока эта проблема не будет решена (это может стать более вероятным, если вы перейдете к этой проблеме в GitHub и дадите ей комментарий или комментарий с убедительным примером использования).
Если выне хочу ждать, вы можете использовать следующий хакерский способ получить что-то вроде этого поведения:
type VerifyKindaPartial<T, KP> =
Partial<T> & {[K in keyof KP]-?: K extends keyof T ? T[K] : never};
const merge = <KP>(value1: MyType, value2: KP & VerifyKindaPartial<MyType, KP>): MyType => {
return { ...value1, ...value2 };
}
Так что вы не можете написать KindaPartial<T>
напрямую.Но вы можете написать тип VerifyKindaPartial<T, KP>
, который принимает тип T
и кандидат тип KP
, который вы хотите сравнить с вашим предполагаемым KindaPartial<T>
.Если кандидат соответствует, то он возвращает что-то, что соответствует KP
.В противном случае он возвращает то, чего нет.
Затем вы создаете merge()
универсальную функцию, которая выводит KP
из типа значения, переданного в value2
.Если KP & VerifyKindaPartial<MyType, KP>
соответствует KP
(это означает, что KP
соответствует KindaPartial<MyType>
), то код скомпилируется.В противном случае, если KP & VerifyKindaPartial<MyType, KP>
не не не соответствует KP
(что означает, что KP
не соответствует KindaPartial<MyType>
), произойдет ошибка.(Ошибка может быть не очень интуитивной, хотя).
Давайте посмотрим:
merge(value, {}); // works
merge(value, { foo: 'bar' }); // works
merge(value, { bar: undefined }); // works
merge(value, { bar: 666 }); // works
merge(value, { foo: '', bar: undefined }); // works
merge(value, { foo: '', bar: 666 }); // works
merge(value, { foo: undefined }); // error!
// ~~~ <-- undefined is not assignable to never
// the expected type comes from property 'foo',
Такое поведение вы хотите ... хотя ошибка, которую вы получаете, немного странная (в идеалебыло бы сказано, что undefined
нельзя присвоить string
, но проблема в том, что компилятор знает, что переданный тип - undefined
, и он хочет, чтобы тип был string
, поэтому компилятор пересекает ихundefined & string
что составляет never
. Хорошо.
В любом случае, здесь есть, вероятно, предостережения: универсальные функции хорошо работают при непосредственном вызове, но они плохо сочетаются, потому что TypeScript не поддерживает более старшие типы.это хорошо. Я не знаю, будет ли это на самом деле работать для вашего случая использования, но это лучшее, что я могу сделать с языком, каким он является в настоящее время.
Надеюсь, это поможет; удачи!