В этой статье вы узнаете о псевдонимах типов и о том, как вы можете определять свои собственные типы в машинописном тексте, а также использовать их в функциях или классах. Наряду с псевдонимами типов я также объяснил, как вы можете использовать Union для создания переменных нескольких типов, что означает, что одна переменная может иметь несколько типов одновременно.

Это будет полная серия машинописных текстов, в которых вы изучите базовые темы, такие как строки, логические значения, и более сложные, такие как псевдонимы типов, перечисления, интерфейс, дженерики и т. д.

Псевдонимы типов

Мы можем использовать объекты, как показано в предыдущем примере, но что, если есть сотни функций, которым нужны одни и те же данные пользователя, тогда вы будете вводить для всех их отдельно, вот где Тип вступает в дело играть. Давайте посмотрим на старый пример и на то, как мы можем использовать type, чтобы сделать его пригодным для повторного использования.

type User = {
  email: string;
  password: string;
};

// ✅ CORRECT
// Passsing Object Type Aliases
function signUp(user: User){}

// ✅ It's the correct way to call
signUp({email: "[email protected]", password: "1233"})

// ❌ ERROR : 'name' does not exist in type 'User'
signUp({email: "[email protected]", password: "1233", name: "Sam"})

// ✅ You can pass extra information by using a variable
let userObj =  {email:  "[email protected]", password:  "1233", name:  "Sam"}
signUp(userObj)

Вы можете использовать псевдоним типа, чтобы дать имя любому типу вообще, а не только объектному типу. Например:

type ID = number;
let userId: ID = 111; // ✅ CORRECT

Думаю, вы поняли, что мы используем type для определения фактического типа переменной. Его можно использовать где угодно.

Только для чтения и необязательно

readonly означает, что пользователь или кто-либо другой не может манипулировать этой переменной, например, id необязательный означает, что эти параметры являются необязательными, которые мы рассмотрели ранее в функциях.

Давайте возьмем пример User, где у пользователя будет три свойства id, email и name.

// Defining the User type
type User = {
    readonly id : string,
    name: string,
    email: string,
}

// Now Let's create a user variable using the above type:
let myUser:User = {
    id : "3947394",
    name: "harry",
    email: "[email protected]",
}

// Now I'll assign the values to the myUser object

// ✅ CORRECT
myUser.name = "Potter";
myUser.email = "[email protected]";

// ❌ ERROR: Cannot assign to 'id' because it is a read-only property
myUser.id = "121324";

Теперь давайте посмотрим на необязательный:

// Defining the User type
type User = {
    readonly id : string,
    name: string,
    email: string,
    dob?: string     // optional
}

// ✅ CORRECT
let user1: User = {
    id : "3947394",
    name: "harry",
    email: "[email protected]",
    dob: "02/12/1998"
}

// ✅ CORRECT
let user2: User = {
    id : "3947394",
    name: "harry",
    email: "[email protected]",
}

Перекресток в type

Вы можете комбинировать два или более типов, используя &. Вы можете сделать это, как показано в следующем коде:

type User = {
    readonly id : string,
    name: string,
    email: string,
}

type Admin = User & {
    key: string, 
}

// You can use Admin like this:
let newAdmin: Admin = {
  id: "3KD5D874",
  name: "Lucifer",
  email: "[email protected]",
  key: "Oh my me!",
};

Псевдонимы типов в функциях

Поскольку я определил несколько типов в приведенном выше коде. Это настраиваемый тип, который вы даже можете использовать в функциях в виде параметров или возвращаемых значений. Вам просто нужно определить type, а затем передать его в качестве параметра.

Введите псевдонимы в качестве параметра функции

 type User = {
    name: string,
    email: string,
    password: string, 
}
// You can use optional variables as well 

// Function that will add user to the database
function addUser(user: User){
    // do some database opertion
}


// ❌ ERROR:  Property 'password' is missing in type '{ name: string; email: string; }' but required in type 'User'
addUser({name: "Rao", email: "[email protected]")
// ✅ CORRECT
addUser({name: "Rao", email: "[email protected]", password: "12345678"})

Введите псевдонимы в качестве возвращаемого значения функции

type User = {
    _id: string 
    name: string,
    email: string,
}

// ✅ CORRECT
function loginUser(id: string): User {
    // performing some operation
    return {_id: id, name: "Joe", email:"[email protected]"}
}

// ❌ ERROR: Property 'email' is missing
function loginUser(id: string): User {
    // performing some operation
    return {_id: id, name: "Joe"}
}

Союз

В Typescript вы можете определить более одного типа переменной. Вы можете сделать это, просто поставив (|) между двумя типами. Позвольте мне показать вам, что я говорю:

let id: string | number;

id = 123;             // ✅
id = "34398493";    // ✅

Оба примера, показанные в приведенном выше коде, верны. Давайте возьмем немного более сложный пример, чтобы понять, как это работает:

type User = {
    name: string,
    id : number
}

type Admin ={
    username: string,
    id: number,
    key: number,
}

let newUser : User | Admin;

// ✅ CORRECT
newUser = {name: "John", id: 123};
newUser = {username : "j333", id : 123, key: 345};
newUser = {name: "j333", id : 123, key: 345};

// ❌ ERROR: Property 'key' is missing
newUser = {username : "j333", id : 123};

Союз в функциях

Вы также можете использовать их с параметрами функции, как показано ниже:

// ✅ It works and id have string and number type
function setUserId(id: string | number){
    console.log(id);
}

// ❌ ERROR : 
// What if we do like this:
function setUserId(id: string | number ){
    id.toLowerCase()  // ❌ ERROR: Property 'toLowerCase' does not exist on type 'number
}

Теперь приведенный выше код покажет вам ошибку, потому что id имеет два типа: string и number.. Строка может быть преобразована в нижний регистр, а число — нет. Вот почему он показывает вам ошибку. Вы можете использовать условный оператор, чтобы делать то, что вам нужно. Такой как:

function setUserId(id: string | number ){
    if (id === "string") {
        id.toLowerCase()
    }
    // do other things
}

Теперь это не даст вам никаких ошибок, потому что мы гарантируем, что toLowerCase() вызывается только тогда, когда id является строкой.

Союз в массиве

В разделе массива мы обсуждали, что можем установить тип массива двумя методами. Но проблема в том, что если нам нужен массив с несколькими типами значений, такими как string и number, что нам делать? Ответ Союз. Теперь давайте посмотрим, как вы это делаете:

// You might be thinking like this
// Nah ❌ you can't do like that
let newArray: number[] | string[] = [1,2, "hello"];

// ✅ Correct way to define the array with multiple type is:
let newArray: (number | string)[] = [1,2, "hello"];

Особый случай для Союза

Теперь представьте, что вы работаете над CSS Framework и разрабатываете файл Button. И вы просите пользователя сказать, какого размера должна быть кнопка. Теперь вы можете использовать тип переменной как string, но пользователь может ввести что угодно, верно? Давайте разберемся с этим на примере:

// ❌ WRONG APPROACH
let ButtonSize: string;

ButtonSize = "big";
ButtonSize = "medium";
ButtonSize = "don't know";  // that's why don't use this

// ✅ CORRECT APPROACH
let ButtonSize : "sm" | "md" | "lg" | "xl";

ButtonSize = "sm";
ButtonSize = "md";
ButtonSize = "lg";
ButtonSize = "xl";

// ❌ ERROR: Type 'large' is not assignable to type
ButtonSize = "large";

Как вы видели в конце приведенного выше кода, машинописный текст запрещает вам назначать large на ButtonSize. Он принимает только специальные типы, определенные вами для кнопки.

Твое задание

Теперь ваша очередь что-то создавать. Итак, для этого вам нужно создать тип для пользователя, который будет иметь следующие свойства:

  • _id: строка, представляющая уникальный идентификатор пользователя.
  • name: строка, представляющая имя пользователя.
  • сообщения: массив объектов, каждый из которых представляет сообщение, сделанное пользователем, со свойствами id, title и body.
  • comments: массив объектов, каждый из которых представляет комментарий, сделанный пользователем, со свойствами id, postId и body.

Подведение итогов

В этой статье я объяснил, что такое псевдонимы типов и как вы можете определять свои собственные типы в машинописном тексте, а также использовать их в функциях или классах. Наряду с псевдонимами типов я также объяснил, как вы можете использовать Union для создания переменных нескольких типов, что означает, что одна переменная может иметь несколько типов одновременно.