Objeto vacío de mecanografiado para una variable escrita

85

Di que tengo:

type User = {
...
}

Quiero crear uno nuevo userpero configurarlo para que sea un objeto vacío:

const user: User = {}; // This fails saying property XX is missing
const user: User = {} as any; // This works but I don't want to use any

¿Cómo hago esto? No quiero que la variable lo sea null.

Kousha
fuente
13
O quiere userser de tipo User | {}o Partial<User>necesita redefinir el Usertipo para permitir un objeto vacío. En este momento, el compilador le está diciendo correctamente que userno es un User.
jcalz

Respuestas:

174

Advertencias

Aquí hay dos salvedades dignas de los comentarios.

O desea que el usuario sea de tipo User | {}o Partial<User>necesita redefinir el Usertipo para permitir un objeto vacío. En este momento, el compilador le está diciendo correctamente que el usuario no es un usuario. -jcalz

No creo que esto deba considerarse una respuesta adecuada porque crea una instancia inconsistente del tipo, socavando todo el propósito de TypeScript. En este ejemplo, la propiedad Usernamese deja sin definir, mientras que la anotación de tipo dice que no puede estar sin definir. -Ian Liu Rodrigues

Responder

Uno de los objetivos de diseño de TypeScript es "lograr un equilibrio entre la corrección y la productividad". Si le resulta productivo hacer esto, use Aserciones de tipo para crear objetos vacíos para las variables escritas.

type User = {
    Username: string;
    Email: string;
}

const user01 = {} as User;
const user02 = <User>{};

user01.Email = "[email protected]";

Aquí hay un ejemplo práctico para ti .

Aquí están las afirmaciones de tipo que funcionan con la sugerencia.

Shaun Luttin
fuente
9
¡Gracias! ¡Esto lo resuelve! Esto debe marcarse como la respuesta correcta ...
Kokodoko
3
No creo que esto deba considerarse una respuesta adecuada porque crea una instancia inconsistente del tipo, socavando todo el propósito de TypeScript. En este ejemplo, la propiedad Usernamese deja sin definir, mientras que la anotación de tipo dice que no puede estar sin definir.
Ian Liu Rodrigues
2
Buen punto @IanLiuRodrigues. Agregué algunas advertencias a la respuesta.
Shaun Luttin
1
@IanLiuRodrigues Uno de los objetivos de TypeScript es equilibrar la corrección con la productividad, por lo que decir que esto socava todo el propósito de TypeScript es un poco extremo. github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
Shaun Luttin
21

Realmente depende de lo que intentes hacer. Los tipos son documentación en mecanografiado, por lo que desea mostrar la intención sobre cómo se supone que se debe usar esto cuando está creando el tipo.

Opción 1: si los usuarios pueden tener algunos de los atributos, pero no todos, durante su vida

Hacer que todos los atributos sean opcionales

type User = {
  attr0?: number
  attr1?: string
}

Opción 2: si las variables que contienen usuarios pueden comenzar como nulo

type User = {
...
}
let u1: User = null;

Aunque, en realidad, aquí si el punto es declarar el objeto Usuario antes de que se sepa qué se le asignará, probablemente desee let u1:Userprescindir de ninguna asignación.

Opción 3: lo que probablemente quieras

Realmente, la premisa del mecanografiado es asegurarse de que se ajusta al modelo mental que esboza en tipos para evitar cometer errores. Si desea agregar cosas a un objeto uno por uno, este es un hábito que TypeScript está tratando de que no haga.

Lo más probable es que desee crear algunas variables locales y luego asignarlas a la variable que contiene el usuario cuando esté lista para ser un usuario completo. De esa forma, nunca te quedarás con un usuario parcialmente formado. Esas cosas son asquerosas.

let attr1: number = ...
let attr2: string = ...
let user1: User = {
  attr1: attr1,
  attr2: attr2
}
pixelpax
fuente
No estoy seguro de si esto es lo que busca o no, pero es posible que estemos hablando de un argumento separado llamado UserAttributes o algo que maneje los parámetros entrantes. Puede que no sea un objeto de usuario aceptable y, por lo tanto, podría definirse por separado.
florece el
Esta no debería ser la respuesta aceptada. Consulte la publicación de Shaun Luttin a continuación.
thargenediad
1

puede hacer esto como se muestra a continuación en mecanografiado

 const _params = {} as any;

 _params.name ='nazeh abel'

Dado que el mecanografiado no se comporta como javascript, tenemos que hacer el tipo como cualquiera, de lo contrario no le permitirá asignar propiedades dinámicamente a un objeto

Nazehs
fuente
0

Si declara un objeto literal vacío y luego asigna valores más adelante, entonces puede considerar esos valores opcionales (pueden o no estar allí), así que simplemente escríbalos como opcionales con un signo de interrogación:

type User = {
    Username?: string;
    Email?: string;
}
CatalinBerta
fuente
0

Tenga en cuenta que el uso const user = {} as UserTypesolo proporciona intellisense, pero en tiempo de ejecución useres un objeto vacío {}y no tiene ninguna propiedad dentro. eso significa user.Emailque dará en undefinedlugar de""

type UserType = {
    Username: string;
    Email: string;
}

Por lo tanto, use classcon constructorpara crear objetos con propiedades predeterminadas.

type UserType = {
  Username: string;
  Email: string;
};

class User implements UserType {
  constructor() {
    this.Username = "";
    this.Email = "";
  }

  Username: string;
  Email: string;
}

const myUser = new User();
console.log(myUser); // output: {Username: "", Email: ""}
console.log("val: "+myUser.Email); // output: ""

También puede usar en interfacelugar detype

interface UserType {
  Username: string;
  Email: string;
};

... y el resto del código sigue siendo el mismo.


En realidad, incluso puede omitir la constructorparte y usarla así:

class User implements UserType {
      Username = ""; // will be added to new obj
      Email: string; // will not be added
}

const myUser = new User();
console.log(myUser); // output: {Username: ""}
GorvGoyl
fuente