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

Вызов всех экспертов Typescript / Flowtype.

Проблема

Мне нужна помощь при наборе функции, с некоторыми неординарными применениями. По сути, это универсальное решение для разных параметров. Он используется в шаблонной функции, где результат всегда должен быть string | string[].

. Параметры будут представлены в виде string | string[] или пары function, args, где аргументы могут или не могут быть присутствовать, и, если присутствует, должно быть Object, которое может иметь или не иметь props или styler в качестве ключей.

Параметр function будет вызываться с аргументами args в качестве единственного параметра. Клавиша props, если она присутствует, будет { [string]: any }, а styler будет { [string]: (string) => string | string[] }

Варианты использования

Это будут некоторые возможные варианты использования (давайте вызовите его execute):

execute('this') => ['this']

execute(() => 'this') => ['this']

execute(
  ({ props: { name } }) => `${name} is awesome`,

  { props: { name: 'this' } }
) => ['this is awesome']

execute(
  ({ styler: { red } }) => `${red('this')}`,

  { styler: { red: (str) => `red ${str}` } }
) => ['red this']

execute(
  ({ 
    props: { name },
    styler: { red }
  }) => `${red(name)} is awesome`

  {
    props: { name: 'this' },
    styler: { red: (str) => `red ${str}` }
  }
) => ['red this is awesome']

Пример ввода

Например, это будут типизированные случаи (не реализация, просто попытка подробно описать как можно больше) в потоке:

type ValidReturnType = string | string[];
type PropsType = {| props: { [string]: any } |};
type StylerType = {| styler: { [string]: (string) => ValidReturnType } |};
type CombinedType<P: PropsType, S: StylerType> = {...P, ...S};

type GetterEmptyType = () => ValidReturn;
type GetterWithPropsType<P: PropsType> = P => ValidReturn;
type GetterWithStylerType<S: StylerType> = S => ValidReturn;
type GetterCombinedType<P: PropsType, S: StylerType> = CombinedType<P, S> => ValidReturn;

// The following would be the parameters (...args) supplied to the execute function
type RedundantGetterParamType<P: void, S: void> = [ValidReturnType, void]
type VoidGetterParamType<P: void, S: void> = [GetterEmpty, void]
type PropsGetterParamType<P: PropsType, S: void> = [GetterWithProps<P>, P];
type StylerGetterParamType<P: void, S: StylerType> = [GetterWithStyler<S>, S];
type CombinedGetterParamType<P: PropsType, S: StylerType> = 
  | [GetterCombined<P, S>, CombinedType<P, S>];

type ExecuteParamsType<P: ?PropsType, S: ?StylerType> =      
    | RedundantGetterParamType<P, S>
    | VoidGetterParamType<P, S>
    | PropsGetterParamType<P, S>
    | StylerGetterParamType<P, S>
    | CombinedGetterParamType<P, S>;

Пример использования

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

Например (максимально обобщенный синтаксис будет отличаться от приведенного выше, для ясности будет сохранен):

const serializeUser = ({ 
  props: { user: { name, surname } }, 
  styler: { 
    red: str => `{red ${str}}`, 
    blue: str => `{blue ${str}}`
  } 
}) => `(Name: ${blue(name)}, Surname: ${red(surname)})`;

const alertTemplate = ({
  props: { code },
}) => `Error ${code}`;

const invalidTemplate = ({
  styler: { purple: str => `{purple ${str}}` } 
}) => purple('invalid')

const errorTemplate = ({
  count,
}) => 
  `${alertTemplate} (${count}): User ${serializeUser} ${() => count > 1 ? 'are' : 'is'}  ${invalidTemplate}! `;

console.log(errorTemplate({ user: { name: "A", surname: "B" }, code: 400, count: 1 });
// => 'Error 400 (3): User (Name: {red A}, Surname: {blue B}) is {purple invalid}! '

В приведенном выше (слишком сложном) примере приведенная в качестве примера функция execute будет использоваться для выражений в шаблоне errorTemplate, оценивая:

  • count в RedundantGetter филиал,
  • () => count > 1 ? 'are' : 'is' на ветви VoidGetter,
  • alertTemplate на ветви PropsGetter,
  • invalidTemplate на ветви StylerGetter
  • serializeUser на ветке CombinedGetter.

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

Заключение

Учитывая Функция execute должна обрабатывать оценку этих ветвей, как объяснено в разделах выше Пример использования Пример использования :

Как бы вы набрали это таким образом способ, которым система ввода (flowtype / typescript) будет выбирать правильный регистр в зависимости от аргументов, учитывая, что некоторые из них могут присутствовать или не присутствовать, и, если они присутствуют, некоторые ключи могут присутствовать или не присутствовать, и корректно отображать тип для intellisense, где это необходимо

...