Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript Support? #49

Open
u3u opened this issue Jul 25, 2018 · 9 comments
Open

TypeScript Support? #49

u3u opened this issue Jul 25, 2018 · 9 comments

Comments

@u3u
Copy link

u3u commented Jul 25, 2018

No description provided.

@DiFuks
Copy link

DiFuks commented Aug 1, 2019

Very much I wait for TS support. Is not enough for this Frankenstein - https://github.com/DiFuks/vue.tsx

@liqueflies
Copy link
Collaborator

I have no experience with TS, I've used only Flow type.
If any of you are interested can submit a PR for this

@RobinRadic
Copy link

RobinRadic commented Oct 18, 2019

Very basic type definitions. Add to a <name>.d.ts file in your project:
If you use tsx and have JSX.InstrinctElements defined somewhere you could swap HTMLElements for JSX.InstrinctElements.

declare module 'vue-styled-components' {
   import * as CSS from 'csstype';
   import * as Vue from 'vue';

   export type CSSProperties = CSS.Properties<string | number>;

   export type CSSPseudos = { [K in CSS.Pseudos]?: CSSObject };

   export interface CSSObject extends CSSProperties, CSSPseudos {
       [ key: string ]: CSSObject | string | number | undefined;
   }

   export type CSS = CSSProperties;

   export type StyledComponent = Vue.Component & Vue.VueConstructor & {
       extend(cssRules: TemplateStringsArray, ...interpolate: TemplateStringsArray[]): StyledComponent
       withComponent(target: Vue.VueConstructor): StyledComponent
   }


   export type StyledComponentElements<T=HTMLElements> = {
       [k in keyof T]:  (str: TemplateStringsArray) =>StyledComponent
   }
   export type Styled<T=HTMLElements> = StyledComponentElements & {
       <T>(Component: T, props?:Record<string,Vue.PropOptions['type']>): (str: TemplateStringsArray) =>StyledComponent
   }

   export interface HTMLElements {
       a: HTMLAnchorElement
       abbr: HTMLElement
       address: HTMLElement
       area: HTMLAreaElement
       article: HTMLElement
       aside: HTMLElement
       audio: HTMLAudioElement
       b: HTMLElement
       base: HTMLBaseElement
       bdi: HTMLElement
       bdo: HTMLElement
       big: HTMLElement
       blockquote: HTMLElement
       body: HTMLBodyElement
       br: HTMLBRElement
       button: HTMLButtonElement
       canvas: HTMLCanvasElement
       caption: HTMLElement
       cite: HTMLElement
       code: HTMLElement
       col: HTMLTableColElement
       colgroup: HTMLTableColElement
       data: HTMLElement
       datalist: HTMLDataListElement
       dd: HTMLElement
       del: HTMLElement
       details: HTMLElement
       dfn: HTMLElement
       dialog: HTMLDialogElement
       div: HTMLDivElement
       dl: HTMLDListElement
       dt: HTMLElement
       em: HTMLElement
       embed: HTMLEmbedElement
       fieldset: HTMLFieldSetElement
       figcaption: HTMLElement
       figure: HTMLElement
       footer: HTMLElement
       form: HTMLFormElement
       h1: HTMLHeadingElement
       h2: HTMLHeadingElement
       h3: HTMLHeadingElement
       h4: HTMLHeadingElement
       h5: HTMLHeadingElement
       h6: HTMLHeadingElement
       head: HTMLElement
       header: HTMLElement
       hgroup: HTMLElement
       hr: HTMLHRElement
       html: HTMLHtmlElement
       i: HTMLElement
       iframe: HTMLIFrameElement
       img: HTMLImageElement
       input: HTMLInputElement
       ins: HTMLModElement
       kbd: HTMLElement
       keygen: HTMLElement
       label: HTMLLabelElement
       legend: HTMLLegendElement
       li: HTMLLIElement
       link: HTMLLinkElement
       main: HTMLElement
       map: HTMLMapElement
       mark: HTMLElement
       menu: HTMLElement
       menuitem: HTMLElement
       meta: HTMLMetaElement
       meter: HTMLElement
       nav: HTMLElement
       noscript: HTMLElement
       object: HTMLObjectElement
       ol: HTMLOListElement
       optgroup: HTMLOptGroupElement
       option: HTMLOptionElement
       output: HTMLElement
       p: HTMLParagraphElement
       param: HTMLParamElement
       picture: HTMLElement
       pre: HTMLPreElement
       progress: HTMLProgressElement
       q: HTMLQuoteElement
       rp: HTMLElement
       rt: HTMLElement
       ruby: HTMLElement
       s: HTMLElement
       samp: HTMLElement
       script: HTMLScriptElement
       section: HTMLElement
       select: HTMLSelectElement
       small: HTMLElement
       source: HTMLSourceElement
       span: HTMLSpanElement
       strong: HTMLElement
       style: HTMLStyleElement
       sub: HTMLElement
       summary: HTMLElement
       sup: HTMLElement
       table: HTMLTableElement
       tbody: HTMLTableSectionElement
       td: HTMLTableDataCellElement
       textarea: HTMLTextAreaElement
       tfoot: HTMLTableSectionElement
       th: HTMLTableHeaderCellElement
       thead: HTMLTableSectionElement
       time: HTMLElement
       title: HTMLTitleElement
       tr: HTMLTableRowElement
       track: HTMLTrackElement
       u: HTMLElement
       ul: HTMLUListElement
       var: HTMLElement
       video: HTMLVideoElement
       wbr: HTMLElement
   }

   export let styled: Styled;

   export default styled;
}

@kahirokunn
Copy link

maybe this declaration is more then better.

declare module 'vue-styled-components' {
  import * as CSS from 'csstype';
  import * as Vue from 'vue';

  export type CSSProperties = CSS.Properties<string | number>;

  export type CSSPseudos = { [K in CSS.Pseudos]?: CSSObject };

  export interface CSSObject extends CSSProperties, CSSPseudos {
    [key: string]: CSSObject | string | number | undefined;
  }

  export type CSS = CSSProperties;

  type VueProps = {
    [propsName: string]: {
      type: new (...args: any[]) => unknown
      default?: unknown
      required?: boolean
      validator?(value: unknown): boolean;
    }
  } | {
    [propsName: string]: new (...args: any[]) => unknown
  }

  type PropsType<Props extends VueProps> = {
    [K in keyof Props]:
    Props[K] extends { type: new (...args: any[]) => unknown } ?
    InstanceType<Props[K]['type']>
    : Props[K] extends new (...args: any[]) => unknown ?
    InstanceType<Props[K]>
    : never
  }

  export type StyledComponent<Props extends VueProps> = Vue.Component & Vue.VueConstructor & {
    extend<U extends VueProps>(cssRules: TemplateStringsArray, ...interpolate: TemplateStringsArray[]): StyledComponent<Props & U>
    withComponent<V extends VueProps>(target: Vue.VueConstructor): StyledComponent<Props & V>
  } & { new(props: PropsType<Props>): Vue.Component }

  export type StyledComponentElements<T = HTMLElements> = {
    [k in keyof T]: (str: TemplateStringsArray) => StyledComponent<{}>
  }

  export type Component = HTMLElements | keyof HTMLElements | Vue.Component | Vue.VueConstructor

  export type Styled = StyledComponentElements & {
    <T extends Component, Props extends VueProps>(Component: T, props?: Props): (str: TemplateStringsArray, ...placeholders: ((props: PropsType<Props>) => string | String | { toString: () => string | String })[]) => StyledComponent<Props>
  }

  export interface HTMLElements {
    a: HTMLAnchorElement
    abbr: HTMLElement
    address: HTMLElement
    area: HTMLAreaElement
    article: HTMLElement
    aside: HTMLElement
    audio: HTMLAudioElement
    b: HTMLElement
    base: HTMLBaseElement
    bdi: HTMLElement
    bdo: HTMLElement
    big: HTMLElement
    blockquote: HTMLElement
    body: HTMLBodyElement
    br: HTMLBRElement
    button: HTMLButtonElement
    canvas: HTMLCanvasElement
    caption: HTMLElement
    cite: HTMLElement
    code: HTMLElement
    col: HTMLTableColElement
    colgroup: HTMLTableColElement
    data: HTMLElement
    datalist: HTMLDataListElement
    dd: HTMLElement
    del: HTMLElement
    details: HTMLElement
    dfn: HTMLElement
    dialog: HTMLDialogElement
    div: HTMLDivElement
    dl: HTMLDListElement
    dt: HTMLElement
    em: HTMLElement
    embed: HTMLEmbedElement
    fieldset: HTMLFieldSetElement
    figcaption: HTMLElement
    figure: HTMLElement
    footer: HTMLElement
    form: HTMLFormElement
    h1: HTMLHeadingElement
    h2: HTMLHeadingElement
    h3: HTMLHeadingElement
    h4: HTMLHeadingElement
    h5: HTMLHeadingElement
    h6: HTMLHeadingElement
    head: HTMLElement
    header: HTMLElement
    hgroup: HTMLElement
    hr: HTMLHRElement
    html: HTMLHtmlElement
    i: HTMLElement
    iframe: HTMLIFrameElement
    img: HTMLImageElement
    input: HTMLInputElement
    ins: HTMLModElement
    kbd: HTMLElement
    keygen: HTMLElement
    label: HTMLLabelElement
    legend: HTMLLegendElement
    li: HTMLLIElement
    link: HTMLLinkElement
    main: HTMLElement
    map: HTMLMapElement
    mark: HTMLElement
    menu: HTMLElement
    menuitem: HTMLElement
    meta: HTMLMetaElement
    meter: HTMLElement
    nav: HTMLElement
    noscript: HTMLElement
    object: HTMLObjectElement
    ol: HTMLOListElement
    optgroup: HTMLOptGroupElement
    option: HTMLOptionElement
    output: HTMLElement
    p: HTMLParagraphElement
    param: HTMLParamElement
    picture: HTMLElement
    pre: HTMLPreElement
    progress: HTMLProgressElement
    q: HTMLQuoteElement
    rp: HTMLElement
    rt: HTMLElement
    ruby: HTMLElement
    s: HTMLElement
    samp: HTMLElement
    script: HTMLScriptElement
    section: HTMLElement
    select: HTMLSelectElement
    small: HTMLElement
    source: HTMLSourceElement
    span: HTMLSpanElement
    strong: HTMLElement
    style: HTMLStyleElement
    sub: HTMLElement
    summary: HTMLElement
    sup: HTMLElement
    table: HTMLTableElement
    tbody: HTMLTableSectionElement
    td: HTMLTableDataCellElement
    textarea: HTMLTextAreaElement
    tfoot: HTMLTableSectionElement
    th: HTMLTableHeaderCellElement
    thead: HTMLTableSectionElement
    time: HTMLElement
    title: HTMLTitleElement
    tr: HTMLTableRowElement
    track: HTMLTrackElement
    u: HTMLElement
    ul: HTMLUListElement
    var: HTMLElement
    video: HTMLVideoElement
    wbr: HTMLElement
  }

  export let styled: Styled;

  export default styled;
}

@theoparis
Copy link

Any updates on this? It's been a couple months..

@silversonicaxel
Copy link

any news?

@kagurazaka-0
Copy link

kagurazaka-0 commented Mar 7, 2021

too type safe with @vue/composition-api

declare module "vue-styled-components" {
  import * as CSS from "csstype"
  import * as Vue from "vue"
  import { defineComponent, ExtractPropTypes } from "@vue/composition-api"
  type ExcludeArrayString<T> = T extends string[] ? never : T
  type VueProps = ExcludeArrayString<Parameters<typeof defineComponent>[0]["props"]>

  export type CSSProperties = CSS.Properties<string | number>

  export type CSSPseudos = { [K in CSS.Pseudos]?: CSSObject }

  export interface CSSObject extends CSSProperties, CSSPseudos {
    [key: string]: CSSObject | string | number | undefined
  }

  export type CSS = CSSProperties

  export type StyledComponent<Props extends VueProps> = Vue.Component &
    Vue.VueConstructor & {
      extend<U extends VueProps>(
        cssRules: TemplateStringsArray,
        ...interpolate: TemplateStringsArray[]
      ): StyledComponent<Props & U>
      withComponent<V extends VueProps>(target: Vue.VueConstructor): StyledComponent<Props & V>
    } & { new (props: ExtractPropTypes<Props>): Vue.Component }

  export type StyledComponentElements = {
    [k in keyof HTMLElementTagNameMap]: (str: TemplateStringsArray) => StyledComponent<{}>
  }

  export type Component = HTMLElementTagNameMap | keyof HTMLElementTagNameMap | Vue.Component | Vue.VueConstructor

  export type Styled = StyledComponentElements & {
    <T extends Component, Props extends VueProps>(Component: T, props?: Props): (
      str: TemplateStringsArray,
      ...placeholders: ((props: ExtractPropTypes<Props>) => string | String | { toString: () => string | String })[]
    ) => StyledComponent<Props>
  }

  export let styled: Styled

  export default styled
}

https://gist.github.com/katsuyaU/e371399f411baba78dc9a43d3303e995

example

import { PropType } from "@vue/composition-api"
import styled from "vue-styled-components"

interface Hoge {
  fuga: number
}

styled("a", {
  requiredProp: { type: String, required: true },
  optionalProp: { type: String },
  objectProp: { type: Object as PropType<Hoge> },
})`
  height:  ${props => props.requiredProp}px;

`

スクリーンショット 2021-03-07 11 24 46

@unseoJang
Copy link

A problem arises injectglobal type
How to solve it?

@danieltvaz
Copy link

What about typing literal strings ? ex:

type MyCompProps = {
value: 'value1' | 'value2';
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants