Порожній об'єкт Typescript для набраної змінної


85

Скажімо, що я маю:

type User = {
...
}

Я хочу створити новий, userале встановити його як порожній об'єкт:

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

Як це зробити? Я не хочу, щоб ця змінна була null.


13
Або ви хочете userбути типу User | {}або Partial<User>, або вам необхідно перевизначити Userтип , щоб порожній об'єкт. Зараз компілятор правильно каже вам, що userце не є User.
jcalz

Відповіді:


176

Застереження

Ось два гідних застереження з коментарів.

Або ви хочете , щоб користувач типу User | {}або Partial<User>, або вам необхідно перевизначити Userтип , щоб порожній об'єкт. Зараз компілятор правильно каже, що користувач не є Користувачем. -jcalz

Я не думаю, що це слід вважати правильною відповіддю, оскільки воно створює непослідовний екземпляр типу, підриваючи цілі призначення TypeScript. У цьому прикладі властивість Usernameзалишається невизначеною, тоді як анотація типу говорить, що її не можна визначити. -Ian Liu Rodrigues

Відповідь

Однією з цілей дизайну TypeScript є "досягнення балансу між коректністю та продуктивністю". Якщо для вас це буде продуктивним, використовуйте твердження типу, щоб створити порожні об'єкти для набраних змінних.

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

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

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

Ось вам робочий приклад .

Ось твердження типу, що працюють із навіюванням.


9
Дякую! Це вирішує це! Це слід позначити як правильну відповідь ...
Кокодоко,

3
Я не думаю, що це слід вважати правильною відповіддю, оскільки воно створює непослідовний екземпляр типу, підриваючи цілі призначення TypeScript. У цьому прикладі властивість Usernameзалишається невизначеною, тоді як анотація типу говорить, що її не можна визначити.
Ян Лю Родрігес

2
Хороший момент @IanLiuRodrigues. Я додав кілька застережень до відповіді.
Шон Луттін,

1
@IanLiuRodrigues Однією з цілей TypeScript є збалансування коректності та продуктивності, тому сказати, що це підриває ціле призначення TypeScript, є дещо екстремальним. github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
Шон Луттін,

21

Дійсно залежить від того, що ви намагаєтесь зробити. Типи - це документація в машинописі, тому ви хочете показати намір щодо того, як цю річ слід використовувати під час створення типу.

Варіант 1: Якщо користувачі можуть мати деякі, але не всі атрибути протягом свого життя

Зробіть усі атрибути необов’язковими

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

Варіант 2: Якщо змінні, що містять Користувачі, можуть починати нуль

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

Хоча насправді тут, якщо справа полягає в оголошенні об’єкта User, перш ніж стане відомо, що йому буде призначено, ви, мабуть, хочете обійтися let u1:Userбез будь-якого призначення.

Варіант 3: Те, що ви, мабуть, хочете

Дійсно, передумова машинопису полягає в тому, щоб переконатися, що ви відповідаєте ментальній моделі, яку ви окреслили в типах, щоб уникнути помилок. Якщо ви хочете додати речі до об’єкта по одному, це звичка, яку TypeScript намагається змусити вас цього не робити.

Швидше за все, ви хочете створити деякі локальні змінні, а потім призначити змісту, що містить користувача, коли вона буде готова стати повноцінним користувачем. Таким чином у вас ніколи не залишиться частково сформований Користувач. Ці речі грубі.

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

Не впевнений, чи це саме те, що він робить, чи ні, але цілком можливо, ми говоримо про окремий аргумент, який називається UserAttributes, або про щось, що обробляє вхідні параметри. Це може бути неприйнятним об'єктом користувача, і, отже, його можна визначити окремо.
відцвітає

Це не повинно бути прийнятою відповіддю. Будь ласка, дивіться допис Шона Луттіна нижче.
thargenediad

1

Ви можете зробити це, як показано нижче в машинописі

 const _params = {} as any;

 _params.name ='nazeh abel'

оскільки typecript не поводиться як javascript, тому ми повинні зробити тип як будь-який інший, інакше це не дозволить вам динамічно призначати властивість об'єкту


0

Якщо ви оголосите порожній літеральний об'єкт, а потім призначите значення пізніше, тоді ви можете вважати ці значення необов'язковими (можуть бути або не бути), тому просто введіть їх як необов'язкові зі знаком питання:

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

0

Зверніть увагу, що використання const user = {} as UserTypejust надає intellisense, але під час виконання userє порожнім об'єктом {}і не має властивості всередині. це засіб user.Emailдасть undefinedзамість""

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

Таким чином, використання classз constructorдля фактичного створення об'єктів з властивостями по замовчуванням.

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

Ви також можете використовувати interfaceзамістьtype

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

... а решта коду залишається незмінною.


Насправді, ви навіть можете пропустити constructorчастину і використовувати її так:

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: ""}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.