• Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

How to Handle Tagged Unions in TypeScript Safely?

Lomanu4 Оффлайн

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,481
Баллы
155
When working with structures in TypeScript, especially when dealing with tagged unions, many developers run into hurdles regarding type safety. The example code you've shared illustrates the challenge of maintaining type integrity while trying to merge two data objects with optional properties. Let's break this down and explore some solutions to avoid using any, which can undermine the benefits of TypeScript's type system.

Understanding Tagged Unions in TypeScript


Tagged unions allow you to define a type that can represent multiple distinct types, providing a way to handle complex data structures safely. However, working with optional fields in a union can complicate interactions between them, particularly in assignment operations.

The Challenge with the Original Code


The original function f(d1: Data, d2: Data) attempts to fill in undefined properties in d1 with corresponding values from d2. The problem arises when attempting to assign d2[key] to d1[key], due to TypeScript's handling of differing types between reading and writing:

const data1: Data = { a: 'hello' };
const data2: Data = { b: 42 };
f(data1, data2);


In this example, TypeScript interprets d1[key] as a union of types including undefined. However, when trying to write value from d2[key] into d1[key], it raises an error since it attempts to assign a broader type to a potentially narrower type. To avoid using any, we can explore some type-safe alternatives.

Step-by-Step Solutions

1. Using Type Assertions


Instead of casting to any, we can refine the types using type assertions more intentionally. We can assert that we are only assigning values that may be non-undefined:

type Data = {
a?: string;
b?: number;
};

function f(d1: Data, d2: Data) {
for (const [key, value] of objEntries(d1)) {
if (value === undefined) {
d1[key as keyof Data] = d2[key] as typeof d1[key];
}
}
}


By using key as keyof Data, we communicate to TypeScript that we have ensured key is appropriate for the structure of Data. This limits type-unsafe operations without needing to revert to any.

2. Conditional Types for Safety


Another method involves creating a utility type to help infer the correct return types for d2[key] based on key:

type Data = {
a?: string;
b?: number;
};

function fillUndefined<T extends Record<string, any>>(source: T, updates: Partial<T>) {
for (const [key, value] of Object.entries(source)) {
if (value === undefined) {
source[key as keyof T] = updates[key] as typeof source[key];
}
}
}


This fillUndefined utility will fill in the blank fields of source from updates, adhering to the type constraints without the risk of using any.

3. Leveraging Utility Types for Enhanced Type Safety


You can also extend this concept further using utility types. Creating a more comprehensive solution allows for type-safe merging of objects:

type Data = {
a?: string;
b?: number;
};

function mergeData<T extends Data>(d1: T, d2: Partial<T>): T {
const result: T = { ...d1 };
for (const key in d2) {
if (d2[key] !== undefined) {
result[key as keyof T] = d2[key] as T[keyof T];
}
}
return result;
}

FAQ

1. Can I use any in TypeScript?


Using any sacrifices type safety, which can lead to runtime errors. Instead, strive for more precise types unless absolutely necessary.

2. How can I test if my TypeScript code is type-safe?


Utilize TypeScript's strict mode, which enforces more rigorous type checks. You can enable this in your tsconfig.json file.

3. What are tagged unions in TypeScript?


Tagged unions allow defining a type that can have multiple types as part of it, facilitating safe handling of values that can belong to multiple types.

Conclusion


Dealing with optional properties in TypeScript can be tricky, especially when aiming to keep code type-safe. By thoughtfully using type assertions, creating utility functions, and leveraging TypeScript's capabilities, you can effectively manage structures without compromising on type safety. This approach will not only help keep your code robust but also enhance maintainability for future developers. Always remember, avoiding any is crucial for leveraging TypeScript's strengths effectively.


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх Снизу