Я публикую сообщение, чтобы узнать, есть ли у кого-нибудь более чистый способ проверки неложных значений в файлах JS/TS.
За прошедшие годы у меня было несколько попыток написать более понятные операторы if для проверки неложных значений, поскольку это заставляло меня задуматься о том, что все они делают одно и то же, но довольно длинные и в конечном итоге занимают половину некоторых файлов кода.
Я пробовал создавать функции и вводить их разными способами, чтобы инкапсулировать журналирование и затем выдавать ошибки, но TS не воспринимает это как безопасную проверку. Пока что единственное, что удовлетворяет проверке, — это стандартный оператор if с ошибкой, выдаваемой непосредственно в теле.
Нет ли лучшего и менее подробного способа обработки этих повторяющихся проверок, сохраняя при этом безопасность?
Стандартные проверки
// Not falsy check
if (!plan) {
Log.log.stripe_webhook("Plan not found");
throw new Error("Plan not found");
}
// Another not falsy check
if (!currentUser.email) {
Log.log.stripe_webhook("Current user does not have an email");
throw new Error("Current user does not have an email");
}
Вещи, которые я пробовал
Вспомогательные функции. Со временем я попробовал несколько вариантов, но вот базовый пример, который TS не принимает.
// Function to ensure no false values. TS does not accept this as safe.
function ensureNotFalsy(
condition: any,
errorMessage: string
): void {
if (!condition) {
Log.log.stripe_webhook(errorMessage);
throw new Error(errorMessage);
}
}
// Not falsy checks
ensureNotFalsy(orgRef, "Organization reference not found");
ensureNotFalsy(orgRef?.organization, "Organization not found");
ensureNotFalsy(
orgRef!.organization!.id,
"Organization ID not found"
);
// ...Code below will still throw errors saying these checked values could be undefined.
Добавление ошибок и обработка в const. Тоже не работает. TS, кажется, требует, чтобы ошибка была выброшена в каждом операторе if.
// Put logic in a const. TS doesn't recognize it as a safe.
const throwError = (message: string) => {
Log.log.stripe_webhook(message);
throw new Error(message);
};
// Checks to ensure not falsy. Doesn't work with TS.
if (!plan) throwError("Plan not found");
if (!currentUser.email)
throwError("Current user does not have an email");
// ...Code below will still throw errors saying these checked values could be undefined.
Кроме того, вы описываете Assert, и он выполняет защиту типа (поэтому он проверяет тип свойства, о котором вы беспокоитесь). Просто это не очень распространенный/популярный способ написания кода на TS/JS.
Привет @BenjaminGruenbaum, спасибо за ответ! В ответ на ваш первый комментарий: я довольно строг, когда дело касается чистого, хорошо структурированного и не подробного кода. Я часто трачу 3/4 своего времени на структурирование файла после написания логики, чтобы обеспечить отсутствие избыточности и простоту. Однако довольно часто, особенно в пошаговых процессах, новые значения вводятся поэтапно и не всегда могут быть определены как единый исходный объект. Описанная мной ситуация редко связана с мутациями, поскольку я обычно печатаю измененное значение, чтобы обеспечить типобезопасность.
Вы пробовали функции утверждения? typescriptlang.org/docs/handbook/release-notes/…
Я не чувствую, что язык работает против меня, я люблю TS, но эти слишком простые утверждения if для неложных значений раздражали меня в течение многих лет, поскольку все они выполняют одну и ту же задачу и занимают так много места. Я вообще редко использую операторы if. Я обнаружил, что 90% операторов if, которые я вижу в коде, обычно можно переписать более понятным и эффективным способом. И одна вещь, которую я действительно ненавижу, — это просматривать файлы и видеть код, написанный разработчиком, который содержит сотни строк операторов if для процессов, которым следует давать имена, добавлять помощники или вместо них использовать операторы переключения.
@GuillaumeBrunerie, я пытался подтвердить, но TS также не считает это безопасным. При использовании утверждения для проверки неложных значений исходный код, использующий эти значения, по-прежнему считает их потенциально неопределенными. Вот ответ GPT о том, почему это не работает: TypeScript's type system does not automatically infer non-nullability from assertions or similar checks by default. TypeScript treats assertions as any other function calls that don't return, but it doesn't understand that they confirm the existence or type of variables unless explicitly told so.
Функции утверждения разработаны именно для этого варианта использования. Ответ от ChatGPT не имеет никакого смысла.
Кроме того, предположим, что вы хотите сократить количество операторов if, проверяя несколько неложных значений за одну проверку. При этом нет прямого способа вернуть настроенную ошибку или журнал, чтобы указать, какое значение не определено, поскольку JS не знает имени значения имени, поэтому вам в конечном итоге придется выдать общую ошибку и журнал, что не всегда принимается в производственном коде. Мой любимый способ справиться с этим — использовать анализ Zod, но не всегда возможно создать схемы Zod для каждого значения.
@GuillaumeBrunerie ниже приведен пример, основанный на исходном коде, которым я поделился, с заменой операторов if на Assert. Тс не принимает ни одного из них. // Asserts check assert.ok(orgRef && orgRef.organization, "Organization not found"); const plan = getPlanProductBy("stripe_price_id", stripePrice); assert.ok(plan, "Plan not found"); try { await createSubscription({ plan_id: plan.id, // TS considers this as possibly null organizationId: orgRef.organization?.id, // Same here
Проверьте мой ответ, функции утверждения работают. Я не понимаю, что вы имеете в виду под assert.ok.
@GuillaumeBrunerie, ты имеешь в виду это, верно? nodejs.org/api/assert.html#assertokvalue-message У вас есть пример?
@MaxPauwels Нет, я имею в виду функции утверждения в Typescript, а не в Node. Посмотрите ссылку, которую я дал выше и в моем ответе.
@GuillaumeBrunerie, это действительно работает! Я не знал об этом; Я действительно ценю совет!



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Функции утверждения созданы именно для этой цели. Просто используйте asserts condition вместо void для возвращаемого типа ensureNotFalsy, и все должно работать.
Вот пример:
function ensureNotFalsy(
condition: any,
errorMessage: string
): asserts condition {
if (!condition) {
throw new Error(errorMessage);
}
}
const f = (orgRef: {organization?: {id?: string}} | null) => {
ensureNotFalsy(orgRef, "Organization reference not found");
ensureNotFalsy(orgRef.organization, "Organization not found");
ensureNotFalsy(
orgRef.organization.id,
"Organization ID not found"
);
}
Именно то, что я искал; Спасибо!
«Нет ли лучшего и менее многословного способа обработки этих повторяющихся проверок, сохраняя при этом безопасность?» - безопасная практика программирования заключается в том, чтобы никогда не иметь объекты в промежуточном состоянии, в котором они могут иметь свойства или нет. Перемещайте больше конкретных объектов меньшего размера, а не большой мутировавший объект с дополнительными свойствами. Вот почему вы чувствуете, что язык «работает против вас», вы можете сделать дополнительные параметры эргономичными с помощью
?.и??и сохранить согласованные схемы для остального.