Переполнение кучи во время компиляции TypeScript или как устранить ошибку кругового (бесконечно глубокого) типа

#typescript #generics #compiler-errors #circular-reference #typescript-generics

#typescript #общие сведения #ошибки компилятора #циклическая ссылка #typescript-общие сведения

Вопрос:

Я разрабатываю строго типизированную библиотеку утилит для проверки типов. TypeScript 3.4.1 в мой проект были внесены новые ошибки во время компиляции. У меня есть Schema тип, который описывает форму некоторого целевого типа. И у меня есть UnpackSchema<TSchema extends Schema> тип, который расширяется до типа, описанного Schema (например, объект схемы времени выполнения { ids: ['number'] } будет описывать статический { ids: number[] } тип).

У меня проблема с круговой ссылкой на тип в UnpackSchema<> теле типа. Поскольку взломы с расширяющимися интерфейсами здесь не помогают, я использую генерацию кода, чтобы вводить множество определений, UnpackSchema<> которые ссылаются на себя линейно, пока они не достигают never типа на самом глубоком уровне. Далее я покажу только небольшую часть UnpackSchema<> определения, и даже когда я создаю 3 экземпляра, UnpackSchema<> tsc зависает на некоторое время и не удается скомпилировать мой код с переполнением кучи. Итак, я отчаянно пытаюсь сильно напечатать свой проект, поскольку даже генерация кода завершается неудачей. Это tsc проблема с производительностью и / или есть ли какой-либо обходной путь, который я могу использовать, чтобы избежать генерации кода здесь?

Мое упрощенное определение UnpackSchema<> выглядит следующим образом (я не буду показывать Schema<> определение, поскольку оно сложное и выходит за рамки):

 export type UnpackSchema<TSchema extends Schema> = (    
    TSchema extends 'string' ? string :
    // ... a lot more cases
    TSchema extends SchemaObj ? UnpackSchemaObject<TSchema> :
    never
);

type SchemaObj = Record<any, Schema>;

// Circular type reference error here
export type UnpackSchemaObject<TObj extends SchemaObj> = MarkUndefinedKeyAsOptional<{
    [TKey in keyof TObj]: UnpackSchema<TObj[TKey]>;
}>;

// adds ? modifier if object's property value contains `undefined` type
type MarkUndefinedKeyAsOptional<TObj> = (
    amp; TObj[Exclude<keyof TObj, GetUndefinedKeysUnion<TObj>>]
    amp; Partial<Pick<TObj, GetUndefinedKeysUnion<TObj>>>
);

type GetUndefinedKeysUnion<TObj> = {
    [TKey in keyof TObj]: TObj[TKey] extends undefined ? TKey : never; 
}[keyof TObj];
  

Отчет о переполнении кучи (при компиляции проекта с tsc ):

Скриншот отчета

Комментарии:

1. Microsoft / TypeScript # 30663 может иметь отношение?

2. Возможно, @jcalz, спасибо, что указали