Objeto vazio de texto digitado para uma variável digitada

88

Diga que tenho:

type User = {
...
}

Quero criar um novo, usermas defini-lo como um objeto vazio:

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

Como eu faço isso? Eu não quero que a variável seja null.

Kousha
fonte
15
Você quer userser do tipo User | {}ou Partial<User>ou precisa redefinir o Usertipo para permitir um objeto vazio. No momento, o compilador está dizendo corretamente que usernão é um User.
jcalz

Respostas:

186

Ressalvas

Aqui estão duas advertências valiosas dos comentários.

Ou você deseja que o usuário seja do tipo User | {}ou Partial<User>, ou você precisa redefinir o Usertipo para permitir um objeto vazio. No momento, o compilador está informando corretamente que o usuário não é um usuário. -jcalz

Não acho que isso deva ser considerado uma resposta adequada porque cria uma instância inconsistente do tipo, minando todo o propósito do TypeScript. Neste exemplo, a propriedade Usernameé deixada indefinida, enquanto a anotação de tipo está dizendo que ela não pode ser indefinida. -Ian Liu Rodrigues

Responda

Um dos objetivos de design do TypeScript é "encontrar um equilíbrio entre correção e produtividade". Se for produtivo para você fazer isso, use Type Assertions para criar objetos vazios para variáveis ​​digitadas.

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

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

user01.Email = "[email protected]";

Aqui está um exemplo prático para você .

Aqui estão as asserções de tipo trabalhando com sugestão.

Shaun Luttin
fonte
9
Obrigado! Isso resolve tudo! Esta deve ser marcada como a resposta correta ...
Kokodoko
3
Não acho que isso deva ser considerado uma resposta adequada porque cria uma instância inconsistente do tipo, minando todo o propósito do TypeScript. Neste exemplo, a propriedade Usernameé deixada indefinida, enquanto a anotação de tipo está dizendo que ela não pode ser indefinida.
Ian Liu Rodrigues
2
Boa observação @IanLiuRodrigues. Eu adicionei algumas advertências à resposta.
Shaun Luttin de
1
@IanLiuRodrigues Um dos objetivos do TypeScript é equilibrar correção com produtividade, então dizer que isso prejudica todo o propósito do TypeScript é um pouco extremo. github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
Shaun Luttin
22

Realmente depende do que você está tentando fazer. Tipos são documentação em texto datilografado, então você deseja mostrar a intenção sobre como isso deve ser usado quando você está criando o tipo.

Opção 1: se os usuários podem ter alguns, mas não todos os atributos durante sua vida

Tornar todos os atributos opcionais

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

Opção 2: se variáveis ​​contendo usuários podem começar nulas

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

Embora, realmente, aqui se o objetivo for declarar o objeto Usuário antes que ele possa ser conhecido o que será atribuído a ele, você provavelmente deseja fazer let u1:Usersem qualquer atribuição.

Opção 3: o que você provavelmente deseja

Na verdade, a premissa do texto datilografado é certificar-se de que você está em conformidade com o modelo mental que delineou em tipos para evitar cometer erros. Se você quiser adicionar coisas a um objeto uma por uma, este é um hábito que o TypeScript está tentando fazer com que você não faça.

Mais provavelmente, você deseja criar algumas variáveis ​​locais e, em seguida, atribuir à variável que contém o usuário quando ela estiver pronta para ser um usuário completo. Dessa forma, você nunca ficará com um usuário parcialmente formado. Essas coisas são nojentas.

let attr1: number = ...
let attr2: string = ...
let user1: User = {
  attr1: attr1,
  attr2: attr2
}
pixelpax
fonte
Não tenho certeza se é isso que ele pretende ou não, mas é possível que estejamos falando sobre um argumento separado chamado UserAttributes ou algo que lida com parâmetros de entrada. Pode não ser um objeto de usuário aceitável e, portanto, pode ser definido separadamente.
desflores em
Esta não deve ser a resposta aceita. Por favor, veja a postagem de Shaun Luttin abaixo.
thargenediad
2

você pode fazer isso como abaixo no texto datilografado

 const _params = {} as any;

 _params.name ='nazeh abel'

já que o typescript não se comporta como javascript, então temos que fazer o tipo como qualquer outro, caso contrário não permitirá que você atribua uma propriedade dinamicamente a um objeto

Nazehs
fonte
2

Observe que o uso const user = {} as UserTypeapenas fornece intellisense, mas em tempo de execução useré um objeto vazio {}e não possui nenhuma propriedade dentro. isso significa que user.Emailvai dar em undefinedvez de""

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

Portanto, use classcom constructorpara criar objetos com propriedades padrão.

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

Você também pode usar em interfacevez detype

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

... e o resto do código permanece o mesmo.


Na verdade, você pode até pular a constructorparte e usá-la assim:

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
fonte
1

Se você declarar um literal de objeto vazio e atribuir valores posteriormente, poderá considerar esses valores opcionais (podem ou não estar lá), então apenas digite-os como opcionais com um ponto de interrogação:

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