Как добавить свойства в стилизованный компонент с Typescript? - PullRequest
0 голосов
/ 21 февраля 2019

У меня есть такие компоненты

import React from 'react';

import styled from '../../styled-components';

const StyledInput = styled.input`
    display: block;
    padding: 5px 10px;
    width: 50%;
    border: none;
    border-radius: 10px;
    outline: none;
    background: ${(props) => props.theme.color.background};
    font-family: 'Roboto', sans-serif;
`
;

export const Input = () => {
    return <StyledInput placeholder="All notes"></StyledInput>
}

Я хочу разместить их как свойство для компонента "index", как этот

import styled from 'styled-components';

import { Input } from './Input';

const NoteTags:any = styled.div`
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 20%;
    height: 5%;
    border-bottom: 2px solid ${(props) => props.theme.color.background}; `;

NoteTags.Input = Input;

export default NoteTags;

Так что я могу использовать их вот так

import React from 'react';

import NoteTags from '../../blocks/note-tags';

const ComponentNoteTags = () => {
    return (
        <React.Fragment>
            <NoteTags.Input></NoteTags.Input>
        </React.Fragment>
    )
}

export default ComponentNoteTags;

Проблема в том, что свойство Input не существует в NoteTags, поэтому машинопись дает мне ошибку.Я могу решить эту проблему, установив тип any в NoteTags, но я не уверен, что это лучший способ.

Есть ли лучший способ исправить это?

1 Ответ

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

Обновление

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

// type-helper.ts
export function withProperties<A, B>(component: A, properties: B): A & B {
  Object.keys(properties).forEach(key => {
    component[key] = properties[key]
  });
  return component as A & B;
}

Примечание: @В комментарии Аллан указывает, что утверждение типа может быть необходимо, например, так:

(component as any)[key] = (properties as any)[key]

, чтобы текст не жаловался на Element implicitly has an 'any' type because type '{}' has no index signature.

Мы просто передаем каждое свойство вproperties до component и присвойте ему оба типа.Затем мы можем «склеить» подкомпоненты в основной компонент следующим образом:

// component/index.ts
import MainComponent from './MainComponent';
import SubComponent1 from './SubComponent1';
import SubComponent2 from './SubComponent2';
import { withProperties } from '../type-helper.ts';

export withProperties(MainComponent, { SubComponent1, SubComponent2 })

и использовать его как обычно

import MainComponent from './Component';

export default () => (
  <MainComponent>
    <SubComponent1 />
    <SubComponent2 />
  </MainComponent>
)

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

Вот демонстрация codesandbox с обоими подходами, которыми я поделился , каждый из которых использует свой код.


Предыдущий ответ

Предполагается, что вы используете последние пакеты:

"styled-components": "^4.1.3",
"@types/styled-components": "^4.1.10",

Вы можете создать тип взаимодействия , который включает оба типа:родительский и дочерний компоненты:

import styled, { StyledComponent } from 'styled-components'
import ChildComponent from '...'

type Component = StyledComponent<'div', any> & {
    ChildComponent: /* your component type */
}

interface IProps {
  ...
}

// create styled component per usual
const MyComponent = styled.div<IProps>`
  ...
` as Component

MyComponent.ChildComponent = ChildComponent;

Вот StyledComponent определение :

export type StyledComponent<
    C extends keyof JSX.IntrinsicElements | React.ComponentType<any>,
    T extends object,       // theme interface
    O extends object = {},  // props interface
    A extends keyof any = never
> = string & StyledComponentBase<C, T, O, A>;

Вы можете использовать его как StyledComponent<C, T, O, A> или StyledComponent<C, T>

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