typescript - Construyendo un objeto de una interfaz en javascript
Tengo una interfaz Person y puedo crear un objeto user1 del tipo Person asignando todas las propiedades a la vez
export interface person {
name: string;
age: number;
city: string;
}
let user1: person = {
name:"ron",
age: 22,
city:"AL"
}
¿Hay una manera de que yo construya este objeto en lugar de asignar todas las propiedades a la vez? Estoy buscando algo como esto
let user2:person;
user2.age = 22;
user2.name = "Dave";
user2.city = "NY"
Respuesta #1
Puedes usar la utilidad de tipo Partial<Type> al inicializar el valor para indicar que las propiedades aún no han sido definidas:
let user: Partial<Person> = {};
Después de inicializar los valores de las propiedades, TypeScript inferirá correctamente que efectivamente existen:
user.age = 22;
user.name = "Dave";
user.city = "NY";
const doubleAge = user.age * 2; // Ok
const lowercaseCity = user.city.toLowerCase(); // Ok
const uppercaseName = user.name.toUpperCase(); // Ok
Campo de Juegos TS
Sin embargo, si no inicializas uno de los valores de las propiedades, TypeScript generará un diagnóstico de error al intentar usarlo:
let user: Partial<Person> = {};
user.age = 22;
const doubleAge = user.age * 2; // Ok
const lowercaseCity = user.city.toLowerCase(); /* Error
~~~~~~~~~
'user.city' is possibly 'undefined'.(18048) */
const uppercaseName = user.name.toUpperCase(); /* Error
~~~~~~~~~
'user.name' is possibly 'undefined'.(18048) */
Campo de Juegos TS
Todavía hay algunos escenarios donde la inferencia no es suficiente — por ejemplo, cuando el valor necesita ser usado como un argumento de una función que requiere un Person:
declare function doSomethingWithPerson(person: Person): void;
let user: Partial<Person> = {};
user.age = 22;
user.name = "Dave";
user.city = "NY";
doSomethingWithPerson(user); /* Error
~~~~
Argument of type 'Partial<Person>' is not assignable to parameter of type 'Person'.
Property 'name' is optional in type 'Partial<Person>' but required in type 'Person'.(2345) */
Campo de Juegos TS
En estos casos, puedes crear una función llamada guardia de tipo que verificará en tiempo de ejecución que el tipo cumpla con las expectativas declaradas. Una guardia de tipo definida por el usuario es una función cuyo tipo de retorno es un predicado de tipo:
function isPerson<T extends Record<PropertyKey, unknown>>(
p: T,
): p is T & Person {
return (
typeof p.age === "number" &&
typeof p.city === "string" &&
typeof p.name === "string"
);
}
Véase también en el manual: genéricos
Entonces puedes verificar si user realmente cumple con la definición de Person antes de usarlo para evitar errores:
let user: Partial<Person> = {};
user.age = 22;
user.name = "Dave";
user.city = "NY";
if (isPerson(user)) {
doSomethingWithPerson(user); // Ok
} else {
// Handle the other case here
}
Campo de Juegos TS
Respuesta #2
Si creas una clase que implemente la interfaz, puedes establecer el valor predeterminado de las propiedades para que estén vacías
class Class implements Person {
name: string = "";
age: number = 0;
city: string = "";
}
y luego configúralos como quieras más tarde
