Я использую [email protected].
У меня есть целевой объект:
interface MyTarget {
a: string;
b: string;
c: string;
d: string;
}
Я хочу создать несколько преобразований частичных объектов с помощью дженериков.
Одно такое преобразование может выглядеть так:
const convert = <T extends object>(t: T): MyTarget => {
return {
c: "c",
d: "d",
...t,
};
};
Тем не менее, это приводит к:
error TS2698: Spread types may only be created from object types.
даже при том, что я защищаю общий T как object.
Затем я вспомнил, что есть тип Partial, поэтому я попробовал это:
const convert = (partial: Partial<MyTarget>): MyTarget => {
return {
c: "c",
d: "d",
...partial,
};
};
Однако Partial делает все свойства необязательными. Я не хочу этого, и теперь он выкинет:
src/Partial.ts(14,5): error TS2322: Type '{ a?: string; b?: string; c: string; d: string; }' is not assignable to type 'MyTarget'.
Property 'a' is optional in type '{ a?: string; b?: string; c: string; d: string; }' but required in type 'MyTarget'.
Я хочу создать экземпляр MyTarget с каждым полем, установленным как требование. Я хочу сохранить безопасность типов, поэтому я не хочу этого, хотя это работает:
const convert = (partial: Partial<MyTarget>): MyTarget => {
return {
c: "c",
d: "d",
...partial,
} as MyTarget; // loses type checks, really don't want to
};






Я думаю, что вы используете более старую версию TS (в более новой версии спред-выражения печатаются правильно).
Независимо от этого, истинная проблема заключается в том, что литерал объекта может не быть полным MyTarget. Ваш код разрешит этот вызов
convert({a : "" })// return value is not really MyTarget since it will not contain b
Что вам действительно нужно, так это параметр MyTarget, кроме c и d:
interface MyTarget {
a: string;
b: string;
c: string;
d: string;
}
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
const convert = (t: Omit<MyTarget, 'c' | 'd'>) : MyTarget => {
return {
c: "c",
d: "d",
...t,
};
};
@k0pernikus k0pernikus Мм ... так действительно, очень старый (то есть 1 год +), я верю, что есть версия Omit для более старых версий. На какой именно версии вы находитесь?
@k0pernikus вот версия Omit для более старых версий, должна быть заменой, но я не проверял: Ideasintosoftware.com/typescript-advanced-tricks
Связанный тип Omit ведет себя не так, как я ожидал: stackoverflow.com/questions/54535539/…
Указанный здесь подход typeof отлично работает: stackoverflow.com/a/48215951/457268
@k0pernikus творческое решение, если вы не возражаете против дополнительных вещей во время выполнения, просто чтобы получить тип. Думаю, я слишком избалован сопоставленными и условными типами :)
Мы все еще используем версию 2.3 для этого проекта, так что нет: я вообще не возражаю против дополнительных вещей во время выполнения. Я принимаю влияние на производительность, чтобы иметь еще один аргумент в пользу будущего обновления;)
Я пошел с Решение Qwerti:
interface XYZ {
x: number;
y: number;
z: number;
}
declare var { z, ...xy }: XYZ;
type XY = typeof xy; // { x: number; y: number;}
который отлично работает для [email protected].
Красиво, жаль, что Exclude существует только с версии 2.8. В настоящее время я не в состоянии обновиться.