Pusty obiekt Typescript dla wpisanej zmiennej

85

Powiedz, że mam:

type User = {
...
}

Chcę utworzyć nowy, userale ustawiłem go jako pusty obiekt:

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

Jak mam to zrobic? Nie chcę, aby zmienna była null.

Kousha
źródło
13
Albo chcesz userbyć typu User | {}lub Partial<User>czy trzeba przedefiniować Usertyp celu umożliwienia pusty obiekt. W tej chwili kompilator poprawnie mówi ci, że usernie jest to plik User.
jcalz

Odpowiedzi:

177

Ostrzeżenia

Oto dwa godne zastrzeżenia z komentarzy.

Albo chcesz użytkownikowi być typu User | {}lub Partial<User>czy trzeba przedefiniować Usertyp celu umożliwienia pusty obiekt. W tej chwili kompilator poprawnie mówi ci, że użytkownik nie jest użytkownikiem. -jcalz

Nie sądzę, aby to było uważane za właściwą odpowiedź, ponieważ tworzy niespójne wystąpienie typu, podważając cały cel TypeScript. W tym przykładzie właściwość Usernamepozostaje niezdefiniowana, podczas gdy adnotacja typu mówi, że nie może być niezdefiniowana. -Ian Liu Rodrigues

Odpowiedź

Jednym z celów projektowych TypeScript jest „osiągnięcie równowagi między poprawnością a produktywnością”. Jeśli będzie to dla Ciebie produktywne, użyj Asercji typu, aby utworzyć puste obiekty dla zmiennych wpisanych.

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

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

user01.Email = "[email protected]";

Oto przykład pracy dla Ciebie .

Oto potwierdzenia typu działające z sugestiami.

Shaun Luttin
źródło
9
Dziękuję Ci! To rozwiązuje problem! To powinno być oznaczone jako poprawna odpowiedź ...
Kokodoko,
3
Nie sądzę, aby to było uważane za właściwą odpowiedź, ponieważ tworzy niespójne wystąpienie typu, podważając cały cel TypeScript. W tym przykładzie właściwość Usernamepozostaje niezdefiniowana, podczas gdy adnotacja typu mówi, że nie może być niezdefiniowana.
Ian Liu Rodrigues
2
Słuszna uwaga @IanLiuRodrigues. Dodałem kilka zastrzeżeń do odpowiedzi.
Shaun Luttin
1
@IanLiuRodrigues Jednym z celów TypeScript jest zrównoważenie poprawności z produktywnością, więc stwierdzenie, że podważa to cały cel TypeScript, jest nieco ekstremalne. github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
Shaun Luttin
22

Naprawdę zależy od tego, co próbujesz zrobić. Typy są dokumentacją w maszynopisie, więc chcesz pokazać zamiar użycia tego elementu podczas tworzenia typu.

Opcja 1: jeśli użytkownicy mogą mieć niektóre, ale nie wszystkie atrybuty w ciągu swojego życia

Ustaw wszystkie atrybuty jako opcjonalne

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

Opcja 2: Jeśli zmienne zawierające Użytkownicy mogą zaczynać się od null

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

Chociaż, tak naprawdę, jeśli chodzi o zadeklarowanie obiektu User, zanim będzie można wiedzieć, co zostanie do niego przypisane, prawdopodobnie chcesz to zrobić let u1:Userbez żadnego przypisania.

Opcja 3: Czego prawdopodobnie chcesz

Naprawdę, założeniem maszynopisu jest upewnienie się, że stosujesz się do modelu mentalnego, który zarysowujesz w typach, aby uniknąć popełnienia błędów. Jeśli chcesz dodawać rzeczy do obiektu jeden po drugim, jest to nawyk, który TypeScript stara się powstrzymać.

Bardziej prawdopodobne jest, że chcesz utworzyć jakieś zmienne lokalne, a następnie przypisać je do zmiennej zawierającej użytkownika, gdy będzie gotowa, aby być pełnym użytkownikiem. W ten sposób nigdy nie zostaniesz z częściowo utworzonym użytkownikiem. Te rzeczy są obrzydliwe.

let attr1: number = ...
let attr2: string = ...
let user1: User = {
  attr1: attr1,
  attr2: attr2
}
pixelpax
źródło
Nie jestem pewien, czy o to chodzi, czy nie, ale możliwe, że mówimy o osobnym argumencie o nazwie UserAttributes lub o czymś, co obsługuje przychodzące parametry. Może to nie być akceptowalny obiekt użytkownika, dlatego można go zdefiniować osobno.
unflores
To nie powinna być akceptowana odpowiedź. Proszę zobaczyć post Shauna Luttina poniżej.
thargenediad
2

możesz to zrobić jak poniżej w maszynopisie

 const _params = {} as any;

 _params.name ='nazeh abel'

ponieważ maszynopis nie zachowuje się jak javascript, więc musimy uczynić typ jak każdy, w przeciwnym razie nie pozwoli on na dynamiczne przypisanie właściwości do obiektu

Nazehowie
źródło
1

Jeśli zadeklarujesz pusty literał obiektu, a następnie przypiszesz wartości później, możesz uznać te wartości za opcjonalne (mogą tam być lub nie), więc po prostu wpisz je jako opcjonalne ze znakiem zapytania:

type User = {
    Username?: string;
    Email?: string;
}
CatalinBerta
źródło
1

Zauważ, że używanie const user = {} as UserTypetylko zapewnia inteligencję, ale w czasie wykonywania userjest pustym obiektem {}i nie ma wewnątrz żadnej właściwości. to znaczy user.Emailda undefinedzamiast""

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

Dlatego używaj classz constructordo faktycznego tworzenia obiektów z domyślnymi właściwościami.

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

Możesz także użyć interfacezamiasttype

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

... a reszta kodu pozostaje taka sama.


Właściwie możesz nawet pominąć tę constructorczęść i użyć jej w ten sposób:

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
źródło