Проверьте типы в аргументе функции generi c и верните объектный литеральный тип этого аргумента - PullRequest
0 голосов
/ 01 марта 2020

Моя задача

У меня есть два интерфейса.

interface ComponentOptions<Props> {
  abstract?: boolean;
  functional: boolean;
  props?: Props;
  name?: string;
  render?(props: Props): boolean;
}

interface ComponentProps {
  title: string;
  dark: boolean;
}

Мне нужно реализовать функцию, которая

  • использует интерфейс для замены Props generi c type
  • выполняет любые проверки, связанные с типом Props в объекте аргумента функции
  • возвращает литеральный тип объекта на основе переданного аргумента объекта
    • делает не возвращается ComponentOptions<Props> интерфейс

strict: true требуется опция компилятора.

Фактическое решение

Я реализовал createComponent функцию, которая получает два аргумента:

  • требуется options литерал объекта
  • props, рассматривается как мнимый аргумент для приведения типа
function createComponent<
  Props,
  Options extends ComponentOptions<Props>
>(options: Options, props: Props): Options {
  props;
  return options;
}

Я достиг желаемый результат с такой реализацией. Но мне это не очень нравится.

const component = createComponent({
  abstract: true,
  functional: true
}, {})

const componentWithProps = createComponent({
  functional: false,
  name: 'bar',
  props: {
    title: 'bar',
    dark: true
  },
  render(props) {
    return props.dark
  }
}, {} as ComponentProps)

Проблема

Я хочу избавиться от аргумента props, оставляя только options, и установить тип для реквизита используя обобщенный параметр c, не приводя аргумент props.

Это может выглядеть так:

const component = createComponent<ComponentProps>({
  functional: true,
  props: { // Check 'title' and 'dark' types
    title: 'comp',
    dark: true
  },
  render(props) { // Pass type for the props
    return props.dark;
  }
})

// When we hover on `component` variable,
// display all defined properties in the `options`
{
  functional: true,
  props: ComponentProps,
  render(props: ComponentProps): boolean
}

Как этого добиться?

Ссылка на игровую площадку

1 Ответ

0 голосов
/ 02 марта 2020

Я решил мою проблему с этим решением:

interface FunctionalComponent<Props> {
  <Options extends ComponentOptions<Props>>(opts: Options): Options
}

function createFunctionalComponent<Props = {}>() {
  return (o => o) as FunctionalComponent<Props>;
}

const component3 = createFunctionalComponent<ComponentProps>()({
  functional: false,
  name: 'bar',
  props: {
    title: 'bar',
    dark: true
  },
  render(props) {
    return props.dark
  }
});
...