¿Hay alguna manera de especificar un tipo parcial en TypeScript que también haga que todos los objetos secundarios también sean parciales? Por ejemplo:
interface Foobar { foo: number; bar: { baz: boolean; qux: string; }; } const foobar: Partial<Foobar> = { foo: 1, bar: { baz: true } };Esto arroja el siguiente error:
TS2741: Property 'qux' is missing in type '{ baz: true; }' but required in type '{ baz: boolean; qux: string; }'.
¿Hay alguna forma de hacer que los nodos secundarios también sean parciales?
Si está buscando una solución rápida y fácil, consulte el paquete type-fest , que tiene muchos tipos útiles de TypeScript precompilados, incluido el tipo PartialDeep .
Para una solución más técnica y personalizable, vea esta respuesta .
Simplemente puede crear un nuevo tipo, digamos, DeepPartial , que básicamente hace referencia a sí mismo (actualizado en enero de 2022 para manejar posibles no objetos):
type DeepPartial<T> = T extends object ? { [P in keyof T]?: DeepPartial<T[P]>; } : T;Entonces, puedes usarlo como tal:
const foobar: DeepPartial<Foobar> = { foo: 1, bar: { baz: true } };Vea el ejemplo de prueba de concepto en TypeScript Playground .
Me inspiré en las respuestas a esta pregunta para crear mi propia versión de PartialDeep.
Me encontré con algunos problemas con los objetos incorporados en el camino; para mi caso de uso, no esperaría que a un objeto Date le falten algunos de sus métodos. O está ahí, o no está.
Aquí está mi versión:
// Primitive types (+ Date) are themselves. Or maybe undefined. type PartialDeep<T> = T extends string | number | bigint | boolean | null | undefined | symbol | Date ? T | undefined // Arrays, Sets and Maps and their readonly counterparts have their items made // deeply partial, but their own instances are left untouched : T extends Array<infer ArrayType> ? Array<PartialDeep<ArrayType>> : T extends ReadonlyArray<infer ArrayType> ? ReadonlyArray<ArrayType> : T extends Set<infer SetType> ? Set<PartialDeep<SetType>> : T extends ReadonlySet<infer SetType> ? ReadonlySet<SetType> : T extends Map<infer KeyType, infer ValueType> ? Map<PartialDeep<KeyType>, PartialDeep<ValueType>> : T extends ReadonlyMap<infer KeyType, infer ValueType> ? ReadonlyMap<PartialDeep<KeyType>, PartialDeep<ValueType>> // ...and finally, all other objects. : { [K in keyof T]?: PartialDeep<T[K]>; };