Как добавить defaultProps в универсальный функциональный компонент с внедрением компонента в TypeScript? - PullRequest
2 голосов
/ 26 сентября 2019

У меня есть функциональный компонент Button, которому требуется пропеллер as для внедрения элемента HTML или другого компонента.Я хочу по умолчанию as prop для Link компонента react-router.Это сделало бы Link 'to prop обязательной опорой Button.Итак, я должен получить сообщение об ошибке при записи <Button>Press me!</Button>, но компилятор не сообщает об ошибке.

Я нахожусь на машинописной версии v3.5.3 со следующими настройками в tsconfig.json:

{
  "compilerOptions": {

    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitThis": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "alwaysStrict": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true
  }
}

Вот моя текущая ситуация (упрощенно) с Link по умолчанию для стиля as es6:

import React from 'react'
import { Link } from 'react-router-dom'

interface ButtonProps {
  children?: string
}

type ElementInjector<T extends React.ElementType> = {
  as: T
} & React.ComponentPropsWithoutRef<T>

export const Button = <T extends React.ElementType>({
  as: Tag = Link,
  ...props
}: ButtonProps & ElementInjector<T>) => {
  return <Tag {...props} />
}

Итак, учитывая вышеизложенное, это результат и ожидания:

<Button>Button</Button>            // error   - asking for `as` not `to`
<Button as={Link}>Button</Button>  // error   - ok
<Button to="/">Button</Button>     // error   - asking for `as`
<Button as="a">Button</Button>     // success - ok

Как получить первый сбой?

Также было бы здорово решить и следующие.Не относится к defaultProps, но к общему подходу.

<Button as="a" to="/">Button</Button>      // success - error expected
<Button<'a'> as="a" to="/">Button</Button> // error   - ok

Пример игры с

1 Ответ

1 голос
/ 26 сентября 2019

Параметр по умолчанию не будет учитываться при выводе параметров типа для компонента.Поскольку нет другого места, где можно взять T, по умолчанию будет unknown.Решением было бы добавить тип по умолчанию для T


export const Button = <T extends React.ElementType = typeof Link>({
    tag: Tag = Link,
    ...props
  }: ButtonProps & ElementInjector<T>) => {
    return <Tag {...props} />
  }

let x = <Button>Button</Button>                      // error expected
let x1 = <Button tag={Link}>Button</Button>          // error   - ok
let x2 = <Button to="/">Button</Button>              // success - ok
let x3 = <Button tag="a">Button</Button>             // success - ok

О вашей второй проблеме, это похоже на этот вопрос, но я не смог заставить его работать, будет публиковать, если у меня есть обновление.

...