Допустимы ли циклические ссылки в файлах .d.ts?

Можно ли при создании объявлений машинописного текста для библиотеки javascript выполнять циклический импорт в файлах .d.ts? Например.:

файл a.d.ts

import { B } from "./b";
export class A { ... }
...

файл b.d.ts

import { A } from "./a";
export interface B { ... }
...

Насколько я понимаю, они используются только для компиляции. Предположим, что в библиотеке javascript нет циклических зависимостей. До сих пор я не обнаружил никаких проблем при использовании объявлений, подобных приведенным выше, в тестовой программе. Мой вопрос в том, является ли такая практика нормальной или считается плохим дизайном, которого следует избегать? Я понимаю, что тот же подход вызовет проблемы во время выполнения (неопределенный экспорт и т. д.), но во время компиляции кажется, что компилятор машинописного текста может их решить (возможно, путем объединения всех объявлений в один модуль?). Или я что-то упустил, и этой практики следует избегать? Если да, можете ли вы привести пример, когда это может вызвать проблему при использовании таких файлов .d.ts?

Попробуй это. Если это работает, то это работает. Если это не так, вам нужно либо изменить то, где у вас есть вещи, либо переосмыслить свои типы.

Samathingamajig 18.04.2023 05:50
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
68
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  1. Когда вы создаете объявления для существующих библиотек JS, вам не нужно заботиться о том, хорошо это или плохо, просто введите их как есть. TS был создан, чтобы охватить как можно больше JS, поэтому, если он работает в JS, он, вероятно, будет работать и в TS.

  2. Циклические ссылки в типах очень распространены и иногда неизбежны, например.

// `parent` can't be just a common interface because exact typings are needed and and DRY
class A {
   parent?: A | B
}
class B {
   parent?: A | B
}

или циклические дженерики

class A<T> { b?: B<T> }
class B<T> { a?: A<T> }

так что они в порядке. Что не в порядке, так это то, что вы используете полный импорт. Вы должны использовать

import type { A } from './a'
//     ^^^^ says it doesn't actually imports that in runtime
  1. Циклические ссылки во время выполнения в коде TS также допустимы, если они создаются до доступа. Это может не поддерживаться модулями commonjs.
// e.g. used in both A and B classes
function makeAorB(x: boolean): A | B { return x ? new A() : new B() }

Примером неудачного создания экземпляра может быть zod TypeError: Cannot read properties of undefined (чтение '_parse')

  1. Если у вас много типов и вы связываете код или что-то еще, вы можете использовать https://www.npmjs.com/package/@microsoft/api-extractor для объединения типов в один файл d.ts.

Итак, в вашем примере в 1 было бы нормально, если бы классы A и B были объявлены в отдельных файлах .d.ts и экспортированы, но внутри этих файлов они должны быть импортированы через «тип импорта»?

Yevgeniy P 18.04.2023 12:42

@YevgeniyP правильно было бы следовать источнику JS. Если './a' ИМПОРТИРУЕТ import './b' или import {...} from './b' во время выполнения, это должно быть import. Если './a' не import './b' во время выполнения, это должно быть import type. т.е. так же, как это было бы в файле TS, который мог бы сгенерировать этот d.ts

Dimava 18.04.2023 12:48

Что, если некоторые или все эти файлы содержат только объявления, используемые во время компиляции (например, интерфейсы и типы), поэтому для них нет исходного кода JS? Если я использую в них «тип импорта», то использование кругового импорта в этих файлах не будет проблемой?

Yevgeniy P 18.04.2023 13:27

Да. Круговой import type — это хорошо, круговой import — нормально, а плохой — это циклический импорт только во время выполнения, ЕСЛИ он немедленно приводит к сбою приложения. Если это не крашит приложение, все в порядке.

Dimava 18.04.2023 13:32

Другие вопросы по теме