Búsqueda de sitios web

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