reshadow icon indicating copy to clipboard operation
reshadow copied to clipboard

How to use reshadow with TypeScript?

Open comerc opened this issue 5 years ago • 14 comments

Property 'container' does not exist on type 'JSX.IntrinsicElements'. TS2339

import React from 'react'
import styled, { css } from 'reshadow/macro'

const styles = css`
  container {
    border: 1px solid red;
  }
`

class ReshadowPage extends React.Component<any> {
  render() {
    return styled(styles)`
      container {
        border: 1px solid green;
      }
    `(<container>Dummy</container>)
  }
}

export default ReshadowPage

comerc avatar Jun 16 '19 09:06 comerc

I do NOT like this solution.

./react-app-env.d.ts

/// <reference types="react-scripts" />

declare namespace JSX {
  interface IntrinsicElements {
    [name: string]: any
  }
}

comerc avatar Jun 16 '19 09:06 comerc

Thank you for the issue. And it is indeed a good one.

This is a good question since I use reshadow daily. But yet to use it in a typescript project.

Off top of my head I can only think of having a list of acceptable component names which will have the same interface a regular div component i.e. same attributes, handlers and so on. This may also be beneficial since you can make sure no one on your team will have typos in component names. This is something which reshadow makes easily forgiven. Another advantage of this approach can be that every one will have a clear list of additional names they can call components instead of winging it as they go. Last one can be controversial but I think it's a good start.

I'm going to have a think about this topic. Perhaps there can be a better solution for this problem. If you have any suggestions please do share!

antonk52 avatar Jun 17 '19 19:06 antonk52

Hi @comerc, thank you for the issue!

In addition to the things that @antonk52 mentioned, I want to note, that there is also possible to use custom elements this way:

<use:container>Dummy</use:container>

And if you don't want to use namespaces:

import styled, {use} from 'reshadow'

styled`
  ...
`
(<use.container>Dummy</use.container>)

I'm not sure that it will work with typescript well because we don't use typescript in our project (we use flow instead), but it looks like it should work.

And this is an undocumented feature, because there are still some things that we need to think about (like, consistent way for declaring elements, should we support the one way described above, or both and so on), but I would be glad if you will give it a try and come back with some feedback 🙂

BTW, we're going to add type declarations for the flow and typescript soon.

lttb avatar Jun 18 '19 07:06 lttb

<use:container> does not work in TypeScript: Parsing error: Identifier expected

How to use use from reshadow?

import styled, {use} from 'reshadow'
...
  render() {
    const { b } = this.state
    const color = b ? 'red' : 'green'
    const width = b ? 1 : 2
    // FIXED: calc() as workaround for dynamic px variable
    // https://github.com/lttb/reshadow/issues/23
    return styled(styles)`
      container {
        border: calc(${width} * 1px) solid ${color};
      }
    `(<use.container onClick={this.handleClick}>Dummy</use.container>)
  }
...

Снимок экрана от 2019-06-23 21-07-33

I see insertion to inline style from variables without border.

comerc avatar Jun 23 '19 18:06 comerc

@comerc from your screenshot I can see that the html element it not getting the class name. Do you have this project on github or codesandbox? I would like to take a closer look. If not than can you make a gist of your config files in order to reproduce the problem?

antonk52 avatar Jun 23 '19 19:06 antonk52

@antonk52

Edit reshadow-cra-wudfn

comerc avatar Jun 24 '19 10:06 comerc

Hi, i'm using typescript 3.2.2 and getting an error when using use namespace. (JSX attribute) use: true Identifier expected.ts(1003)

<button use:size={size} use:bg={bg}>
	{props.children}
</button>

gus3inov avatar Jul 10 '19 07:07 gus3inov

hi @gus3inov, at this moment it would be better to use the use function, because it looks like TS parser does not support namespaces

import {use} from 'reshadow'

<button {...use({size, bg})}>
	{props.children}
</button>

lttb avatar Jul 11 '19 09:07 lttb

Thanks for feedback @lttb ! use function worked for me, but i'm think it's bad for typings component. What if I add pull request with types like these ?

const _Symbol = (key: string) => (typeof Symbol !== 'undefined' ? Symbol(key) : key);

const use = <T>(obj: T) => {
    const result: {use: T} = {
        use: obj
    };
    return result;
};

gus3inov avatar Jul 11 '19 09:07 gus3inov

const _Symbol = (key: string) => (typeof Symbol !== 'undefined' ? Symbol(key) : key);

const use = <T>(obj: T) => {
    const result: {use: T} = {
        use: obj
    };
    return result;
};

I'm not sure, that this is correct, because in fact the type of use function is something like

declare function use<T: {[string]: string | number | boolean}>(T): {||}

because the result will be omitted in the runtime and will not affect the component/element interface

lttb avatar Jul 11 '19 09:07 lttb

Yes, you are right, generic constraint looks good.

gus3inov avatar Jul 11 '19 09:07 gus3inov

@comerc @gus3inov we've just released the 0.0.1-alpha.69 version with basic typescript and flowtype support, there is an example of next + reshadow + typescript: https://codesandbox.io/s/reshadow-next-typescript-yok5b

hope to add some docs with examples and explanation soon

lttb avatar Sep 26 '19 17:09 lttb

I see "Container Error"

Снимок экрана от 2019-09-30 21-54-29

comerc avatar Sep 30 '19 18:09 comerc

Another issue is undeclared styled.styles: image

artalar avatar Jul 02 '20 07:07 artalar