Oggetto vuoto dattiloscritto per una variabile digitata


88

Di 'che ho:

type User = {
...
}

Voglio creare un nuovo userma impostarlo come un oggetto vuoto:

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

Come faccio a fare questo? Non voglio che la variabile sia null.


15
O vuoi useressere di tipo User | {}oppure Partial<User>devi ridefinire il Usertipo per consentire un oggetto vuoto. In questo momento, il compilatore ti sta dicendo correttamente che usernon è un file User.
jcalz

Risposte:


186

Avvertenze

Ecco due degni avvertimenti dai commenti.

O si desidera che l'utente sia di tipo User | {}oppure Partial<User>è necessario ridefinire il Usertipo per consentire un oggetto vuoto. In questo momento, il compilatore ti sta dicendo correttamente che l'utente non è un utente. -jcalz

Non penso che questa debba essere considerata una risposta corretta perché crea un'istanza incoerente del tipo, minando l'intero scopo di TypeScript. In questo esempio, la proprietà Usernameviene lasciata indefinita, mentre l'annotazione del tipo dice che non può essere indefinita. -Ian Liu Rodrigues

Risposta

Uno degli obiettivi di progettazione di TypeScript è "trovare un equilibrio tra correttezza e produttività". Se sarà produttivo per te farlo, usa le asserzioni di tipo per creare oggetti vuoti per le variabili digitate.

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

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

user01.Email = "foo@bar.com";

Ecco un esempio funzionante per te .

Ecco le asserzioni di tipo che lavorano con il suggerimento.


9
Grazie! Questo lo risolve! Questa dovrebbe essere contrassegnata come risposta corretta ...
Kokodoko

3
Non penso che questa debba essere considerata una risposta corretta perché crea un'istanza incoerente del tipo, minando l'intero scopo di TypeScript. In questo esempio, la proprietà Usernameviene lasciata indefinita, mentre l'annotazione del tipo dice che non può essere indefinita.
Ian Liu Rodrigues

2
Buon punto @IanLiuRodrigues. Ho aggiunto alcuni avvertimenti alla risposta.
Shaun Luttin

1
@IanLiuRodrigues Uno degli obiettivi di TypeScript è quello di bilanciare la correttezza con la produttività, quindi dire che questo mina l'intero scopo di TypeScript è un po 'estremo. github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
Shaun Luttin

22

Dipende davvero da cosa stai cercando di fare. I tipi sono documentazione in dattiloscritto, quindi vuoi mostrare l'intenzione su come dovrebbe essere usata questa cosa quando crei il tipo.

Opzione 1: se gli utenti possono avere alcuni ma non tutti gli attributi durante la loro vita

Rendi facoltativi tutti gli attributi

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

Opzione 2: se le variabili contenenti Users possono iniziare con null

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

Anche se, in realtà, qui se il punto è dichiarare l'oggetto User prima di poter sapere cosa gli verrà assegnato, probabilmente vorrai fare a let u1:Usermeno di alcun assegnamento.

Opzione 3: quello che probabilmente vuoi

In realtà, la premessa del dattiloscritto è assicurarsi di conformarsi al modello mentale che si delinea nei tipi per evitare di commettere errori. Se vuoi aggiungere cose a un oggetto una per una, questa è un'abitudine che TypeScript sta cercando di farti non fare.

Più probabilmente, desideri creare alcune variabili locali, quindi assegnarle alla variabile contenente l'utente quando è pronta per essere un utente completo. In questo modo non sarai mai lasciato con un utente parzialmente formato. Quelle cose sono disgustose.

let attr1: number = ...
let attr2: string = ...
let user1: User = {
  attr1: attr1,
  attr2: attr2
}

Non sono sicuro se questo sia ciò che sta cercando o meno, ma è possibile che stiamo parlando di un argomento separato chiamato UserAttributes o qualcosa che gestisce i parametri in arrivo. Potrebbe non essere un oggetto utente accettabile e quindi potrebbe essere definito separatamente.
unflores

Questa non dovrebbe essere la risposta accettata. Si prega di vedere il post di Shaun Luttin di seguito.
thargenediad

2

puoi farlo come sotto in dattiloscritto

 const _params = {} as any;

 _params.name ='nazeh abel'

dato che il dattiloscritto non si comporta come javascript quindi dobbiamo rendere il tipo come un qualsiasi altrimenti non ti permetteràdi assegnare dinamicamente la proprietà a un oggetto


2

Si noti che l'utilizzo const user = {} as UserTypefornisce solo intellisense ma in fase di esecuzione userè un oggetto vuoto {}e non ha proprietà all'interno. ciò significa user.Emailche darà undefinedinvece di""

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

Quindi, usa classcon constructorper creare effettivamente oggetti con proprietà predefinite.

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: ""

Puoi anche usare al interfaceposto ditype

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

... e il resto del codice rimane lo stesso.


In realtà, puoi persino saltare la constructorparte e usarla in questo modo:

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: ""}

1

Se dichiari un oggetto letterale vuoto e quindi assegni valori in un secondo momento, puoi considerare quei valori facoltativi (possono o non possono essere presenti), quindi digitali come facoltativi con un punto interrogativo:

type User = {
    Username?: string;
    Email?: string;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.