преобразовать интерфейс таким образом, что вхождения одного типа заменяются машинописным текстом другого типа - PullRequest
0 голосов
/ 05 августа 2020

У меня есть функция, которая просматривает данный общий c объект (типа T), а затем преобразует определенные свойства типа в другой тип. Мне нужна эта функция, чтобы также обновить тип ввода (T), чтобы отразить изменения в вводе, выполненном функцией.

Я пытаюсь выполнить sh следующее: given Interface1:

interface Interface1 {
  prop1: Type1
  prop2: Type2
  prop3: {
    subprop1: Type1
    subprop2: Type2
  }
}

, тогда мне нужно выражение типа, например Transform<T>, такое, что выполнение Transform<Interface1> приводит к:

interface Interface2 {
  prop1: NewType
  prop2: Type2
  prop3: {
    subprop1: NewType
    subprop2: Type2
  }
}

Ответы [ 2 ]

0 голосов
/ 06 августа 2020

я бы предложил что-то вроде этого:

type Rep<T, R, Target> = Target extends T 
  ? R 
  : Target extends Object 
    ? { [K in keyof Target]: Rep<T, R, Target[K]> } 
    : Target extends infer X 
      ? X 
      : never

, например, для:

interface Interface1 {
  prop1: number
  prop2: string
  prop3: {
    subprop1: string
    subprop2: {
        subprop2_1: number,
        subpeop2_2: {
            subprop2_2_1: number
        }
    }
    subprop3 : number
  }
}

замена всех number s на {x: string} может выглядеть так:

type T1 = Rep<number, { x: string }, Interface1>

создание этой подписи типа:

type T1 = {
  prop1: {
    x: string;
  };
  prop2: string;
  prop3: {
    subprop1: string;
    subprop2: {
      subprop2_1: {
        x: string;
      };
      subpeop2_2: {
        subprop2_2_1: {
          x: string;
        };
      };
    };
    subprop3: {
      x: string;
    };
  };
}

ссылка tsplayground

0 голосов
/ 05 августа 2020

Это можно сделать - но какой ценой?

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

Это сделает то, о чем вы просите - где T - это тип объекта для преобразования, TTarget - это Type1, а TResult - это NewType

First - более простая форма, которая лениво вычисляет. Это означает, что вы получите следующий результат при наведении курсора на тип результата:

1008 *enter image description here
type Transform1 = {
    [key in keyof T]:
        T[key] extends object
            ? Transform1
            : T[key] extends TTarget ? TReplacement : T[key];
} 

This version will eagerly evaluate the nested object - giving you more 'correct' looking type hints

enter image description here

type Transform2 = {
    [key in keyof T]:
        T[key] extends object
            ? {
                [innerKey in keyof Transform2]:
                    Transform2[innerKey]
              }
            : T[key] extends TTarget ? TReplacement : T[key];
} 

How this works is that we first map over T using a mapped type -

{ [key in keyof T]: T[key] }

Next we need to check if T[key] is a nested object, and if so - we need to recurse the type. We do this by asking if T[key] extends object. If it does, Transform again.

Then we can check if T[key] is assignable to the TTarget we are trying to replace with T[key] extends TTarget. If it does, return TReplacement, otherwise leave it alone by returning T[key].

The eagerly evaluated version just uses a little trick where we map over the result type again.

We are doing the same {[key in T]: T[key]} - except we replace T with the thing we want to evaluate - which is Transform. We also need another variable for key, because we're now mapping over the inner type, so I used innerKey here.

This gives us

{ [innerKey in keyof Transform2]: Transform2[innerKey] }

Playground link: https://www.typescriptlang.org/play?#code / C4TwDgpgBAKuEEYoF4oGdgCcCWA7A5gNwBQoks8ATClAEYD29ANhAIa4lnQByEA7nHKpcAVwC2tCJhLE8wKQDNWAY2gBJXPMxLVSAN7EoUMJnpgEALgqQEh46bCUrgiJTsmzAZisGjRtCK0HubO8LZ + 6IHBTtaudgC + xImymooq6qna6dS + 9maWULwC8O4OMS5uRsHeULn + UQ4FRS529UFloZCVUInJAPR9sAAW2GhQfNhMTFBMrABekyBQEABurEwirPJQwEPQuBAYEAAmUPS0AFYQysCk8LCY7GgK9JhiCAA8MMsAHvK4xzG5yuNwANLAYKxMPgIMBwTAAEoQMCzVRiCCaAB8NDqUAA2gBrCBLPBQIkgegKWAAXQsrQisEJxOpv3 + gLOl2utwZPKgAH4Hk8Xm9PjAmSBqfDIdDYfCkSj0uisfTeVBnOKWRA-hj2TBpTDgPzYPLURAlYb1eTqSR4lBiMQBsNRuNJtM2DDMEwlqt1pttrt9od5KdgVyoABaKD4bArPD4KAUkRQMSvaAAcmUr0wXLTM0YBLjO3uI00aDu5Bgj1wz1eYkoX1ZOqBnLBEKhBrlyNN5uxqFx4qgpPJlJpdNVYqtjYBzZB3NVfgFuPnfjxeAOmAA0sTB7gycSR5WhbX6xPmVL27LjV3FRjgJjaSrlwzD9XhXWvhrzzK4VeFWjb5iq64OuW4So + qqJE + aqMpOWpsmMeoXoaAqIte -6aNBp4Sjadr2o6AAS9ArFIZzEZgUBIgETDAEgwD0OgEDQFwUAlrczGUSI1FIKgL41iKHwaFoOiIPCYTgs08CYjIBFESRsnkRx1HUHRDFMiin76cjAn * 10CYJBFESRsnkRx1HUHRDFMiC1CJP * 10CYNFMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXVX

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...